[RFC][PATCH 4/4] perf/events: Use helper functions in event assignment to shrink macro size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


From: Steven Rostedt <srostedt@xxxxxxxxxx>

The functions that assign the contents for the perf software events are
defined by the TRACE_EVENT() macros. Each event has its own unique
way to assign data to its buffer. When you have over 700 events,
that means there's 700 functions assigning data uniquely for each
event.

By making helper functions in the core kernel to do the work
instead, we can shrink the size of the kernel down a bit.

With a kernel configured with 707 events, the change in size was:

   text    data     bss     dec     hex filename
19966937        2594648 1945600 24507185        175f331 vmlinux-before
19924761        2594584 1945600 24464945        1754e31 vmlinux-after

That's a total of 42240 bytes, which comes down to 59 bytes per event.

Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
---
 include/linux/ftrace_event.h    |   13 +++++++++++++
 include/trace/ftrace.h          |   31 ++++++++-----------------------
 kernel/trace/trace_event_perf.c |   26 ++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 23 deletions(-)

diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index b9f39d3..06c6d04 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -313,6 +313,19 @@ struct perf_event;
 
 DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
 
+struct perf_trace_event {
+	struct pt_regs		regs;
+	u64			addr;
+	u64			count;
+	int			entry_size;
+	int			rctx;
+};
+
+extern void *perf_trace_event_setup(struct ftrace_event_call *event_call, 
+				    struct perf_trace_event *pe);
+extern void perf_trace_event_submit(void *raw_data, struct ftrace_event_call *event_call,
+				    struct perf_trace_event *pe);
+
 extern int  perf_trace_init(struct perf_event *event);
 extern void perf_trace_destroy(struct perf_event *event);
 extern int  perf_trace_add(struct perf_event *event, int flags);
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 8118451..a02d48d 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -677,10 +677,10 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
 #define __get_str(field) (char *)__get_dynamic_array(field)
 
 #undef __perf_addr
-#define __perf_addr(a) __addr = (a)
+#define __perf_addr(a) __pe.addr = (a)
 
 #undef __perf_count
-#define __perf_count(c) __count = (c)
+#define __perf_count(c) __pe.count = (c)
 
 #undef TP_perf_assign
 #define TP_perf_assign(args...) args
@@ -693,36 +693,21 @@ perf_trace_##call(void *__data, proto)					\
 	struct ftrace_event_call *event_call = __data;			\
 	struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
 	struct ftrace_raw_##call *entry;				\
-	struct pt_regs __regs;						\
-	u64 __addr = 0, __count = 1;					\
-	struct hlist_head *head;					\
-	int __entry_size;						\
+	struct perf_trace_event __pe;					\
 	int __data_size;						\
-	int rctx;							\
-									\
-	perf_fetch_caller_regs(&__regs);				\
 									\
 	__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
-	__entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
-			     sizeof(u64));				\
-	__entry_size -= sizeof(u32);					\
-									\
-	if (WARN_ONCE(__entry_size > PERF_MAX_TRACE_SIZE,		\
-		      "profile buffer not large enough"))		\
-		return;							\
+	__pe.entry_size = __data_size + sizeof(*entry);			\
+	__pe.addr = 0;							\
+	__pe.count = 1;							\
 									\
-	entry = (struct ftrace_raw_##call *)perf_trace_buf_prepare(	\
-		__entry_size, event_call->event.type, &__regs, &rctx);	\
-	if (!entry)							\
-		return;							\
+	entry = perf_trace_event_setup(event_call, &__pe);		\
 									\
 	tstruct								\
 									\
 	{ assign; }							\
 									\
-	head = this_cpu_ptr(event_call->perf_events);			\
-	perf_trace_buf_submit(entry, __entry_size, rctx, __addr,	\
-		__count, &__regs, head);				\
+	perf_trace_event_submit(entry, event_call, &__pe);		\
 }
 
 /*
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 9824419..75484aa 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -21,6 +21,32 @@ typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
 /* Count the events in use (per event id, not per instance) */
 static int	total_ref_count;
 
+void *perf_trace_event_setup(struct ftrace_event_call *event_call, 
+			     struct perf_trace_event *pe)
+{
+	perf_fetch_caller_regs(&pe->regs);
+
+	pe->entry_size = ALIGN(pe->entry_size + sizeof(u32), sizeof(u64));
+	pe->entry_size -= sizeof(u32);
+
+	if (WARN_ONCE(pe->entry_size > PERF_MAX_TRACE_SIZE,
+		      "profile buffer not large enough"))
+		return NULL;
+
+	return perf_trace_buf_prepare(pe->entry_size,
+			event_call->event.type, &pe->regs, &pe->rctx);
+}
+
+void perf_trace_event_submit(void *raw_data, struct ftrace_event_call *event_call,
+			     struct perf_trace_event *pe)
+{
+	struct hlist_head *head;
+
+	head = this_cpu_ptr(event_call->perf_events);
+	perf_trace_buf_submit(raw_data, pe->entry_size, pe->rctx, pe->addr,
+			      pe->count, &pe->regs, head);
+}
+
 static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
 				 struct perf_event *p_event)
 {
-- 
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Other Archives]     [Linux Kernel Newbies]     [Linux Driver Development]     [Linux Kbuild]     [Fedora Kernel]     [Linux Kernel Testers]     [Linux SH]     [Linux Omap]     [Linux Tape]     [Linux Input]     [Linux Kernel Janitors]     [Linux Kernel Packagers]     [Linux Doc]     [Linux Man Pages]     [Linux API]     [Linux Memory Management]     [Linux Modules]     [Linux Standards]     [Kernel Announce]     [Netdev]     [Git]     [Linux PCI]     Linux CAN Development     [Linux I2C]     [Linux RDMA]     [Linux NUMA]     [Netfilter]     [Netfilter Devel]     [SELinux]     [Bugtraq]     [FIO]     [Linux Perf Users]     [Linux Serial]     [Linux PPP]     [Linux ISDN]     [Linux Next]     [Kernel Stable Commits]     [Linux Tip Commits]     [Kernel MM Commits]     [Linux Security Module]     [AutoFS]     [Filesystem Development]     [Ext3 Filesystem]     [Linux bcache]     [Ext4 Filesystem]     [Linux BTRFS]     [Linux CEPH Filesystem]     [Linux XFS]     [XFS]     [Linux NFS]     [Linux CIFS]     [Ecryptfs]     [Linux NILFS]     [Linux Cachefs]     [Reiser FS]     [Initramfs]     [Linux FB Devel]     [Linux OpenGL]     [DRI Devel]     [Fastboot]     [Linux RT Users]     [Linux RT Stable]     [eCos]     [Corosync]     [Linux Clusters]     [LVS Devel]     [Hot Plug]     [Linux Virtualization]     [KVM]     [KVM PPC]     [KVM ia64]     [Linux Containers]     [Linux Hexagon]     [Linux Cgroups]     [Util Linux]     [Wireless]     [Linux Bluetooth]     [Bluez Devel]     [Ethernet Bridging]     [Embedded Linux]     [Barebox]     [Linux MMC]     [Linux IIO]     [Sparse]     [Smatch]     [Linux Arch]     [x86 Platform Driver]     [Linux ACPI]     [Linux IBM ACPI]     [LM Sensors]     [CPU Freq]     [Linux Power Management]     [Linmodems]     [Linux DCCP]     [Linux SCTP]     [ALSA Devel]     [Linux USB]     [Linux PA RISC]     [Linux Samsung SOC]     [MIPS Linux]     [IBM S/390 Linux]     [ARM Linux]     [ARM Kernel]     [ARM MSM]     [Tegra Devel]     [Sparc Linux]     [Linux Security]     [Linux Sound]     [Linux Media]     [Video 4 Linux]     [Linux IRDA Users]     [Linux for the blind]     [Linux RAID]     [Linux ATA RAID]     [Device Mapper]     [Linux SCSI]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Linux IDE]     [Linux SMP]     [Linux AXP]     [Linux Alpha]     [Linux M68K]     [Linux ia64]     [Linux 8086]     [Linux x86_64]     [Linux Config]     [Linux Apps]     [Linux MSDOS]     [Linux X.25]     [Linux Crypto]     [DM Crypt]     [Linux Trace Users]     [Linux Btrace]     [Linux Watchdog]     [Utrace Devel]     [Linux C Programming]     [Linux Assembly]     [Dash]     [DWARVES]     [Hail Devel]     [Linux Kernel Debugger]     [Linux gcc]     [Gcc Help]     [X.Org]     [Wine]

Add to Google Powered by Linux

[Older Kernel Discussion]     [Yosemite National Park Forum]     [Large Format Photos]     [Gimp]     [Yosemite Photos]     [Stuff]