Skip to content

Commit d1a2914

Browse files
Steven Rostedtrostedt
authored andcommitted
tracing: Use kmem_cache_alloc instead of kmalloc in trace_events.c
The event structures used by the trace events are mostly persistent, but they are also allocated by kmalloc, which is not the best at allocating space for what is used. By converting these kmallocs into kmem_cache_allocs, we can save over 50K of space that is permanently allocated. After boot we have: slab name active allocated size --------- ------ --------- ---- ftrace_event_file 979 1005 56 67 1 ftrace_event_field 2301 2310 48 77 1 The ftrace_event_file has at boot up 979 active objects out of 1005 allocated in the slabs. Each object is 56 bytes. In a normal kmalloc, that would allocate 64 bytes for each object. 1005 - 979 = 26 objects not used 26 * 56 = 1456 bytes wasted But if we used kmalloc: 64 - 56 = 8 bytes unused per allocation 8 * 979 = 7832 bytes wasted 7832 - 1456 = 6376 bytes in savings Doing the same for ftrace_event_field where there's 2301 objects allocated in a slab that can hold 2310 with 48 bytes each we have: 2310 - 2301 = 9 objects not used 9 * 48 = 432 bytes wasted A kmalloc would also use 64 bytes per object: 64 - 48 = 16 bytes unused per allocation 16 * 2301 = 36816 bytes wasted! 36816 - 432 = 36384 bytes in savings This change gives us a total of 42760 bytes in savings. At least on my machine, but as there's a lot of these persistent objects for all configurations that use trace points, this is a net win. Thanks to Ezequiel Garcia for his trace_analyze presentation which pointed out the wasted space in my code. Cc: Ezequiel Garcia <elezegarcia@gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
1 parent 7724822 commit d1a2914

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

kernel/trace/trace_events.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ EXPORT_SYMBOL_GPL(event_storage);
3636
LIST_HEAD(ftrace_events);
3737
LIST_HEAD(ftrace_common_fields);
3838

39+
#define GFP_TRACE (GFP_KERNEL | __GFP_ZERO)
40+
41+
static struct kmem_cache *field_cachep;
42+
static struct kmem_cache *file_cachep;
43+
3944
/* Double loops, do not use break, only goto's work */
4045
#define do_for_each_event_file(tr, file) \
4146
list_for_each_entry(tr, &ftrace_trace_arrays, list) { \
@@ -63,7 +68,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
6368
{
6469
struct ftrace_event_field *field;
6570

66-
field = kzalloc(sizeof(*field), GFP_KERNEL);
71+
field = kmem_cache_alloc(field_cachep, GFP_TRACE);
6772
if (!field)
6873
goto err;
6974

@@ -91,7 +96,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
9196
err:
9297
if (field)
9398
kfree(field->name);
94-
kfree(field);
99+
kmem_cache_free(field_cachep, field);
95100

96101
return -ENOMEM;
97102
}
@@ -143,7 +148,7 @@ void trace_destroy_fields(struct ftrace_event_call *call)
143148
list_del(&field->link);
144149
kfree(field->type);
145150
kfree(field->name);
146-
kfree(field);
151+
kmem_cache_free(field_cachep, field);
147152
}
148153
}
149154

@@ -1383,7 +1388,7 @@ static void remove_event_from_tracers(struct ftrace_event_call *call)
13831388
list_del(&file->list);
13841389
debugfs_remove_recursive(file->dir);
13851390
remove_subsystem(file->system);
1386-
kfree(file);
1391+
kmem_cache_free(file_cachep, file);
13871392

13881393
/*
13891394
* The do_for_each_event_file_safe() is
@@ -1462,7 +1467,7 @@ __trace_add_new_event(struct ftrace_event_call *call,
14621467
{
14631468
struct ftrace_event_file *file;
14641469

1465-
file = kzalloc(sizeof(*file), GFP_KERNEL);
1470+
file = kmem_cache_alloc(file_cachep, GFP_TRACE);
14661471
if (!file)
14671472
return -ENOMEM;
14681473

@@ -1484,7 +1489,7 @@ __trace_early_add_new_event(struct ftrace_event_call *call,
14841489
{
14851490
struct ftrace_event_file *file;
14861491

1487-
file = kzalloc(sizeof(*file), GFP_KERNEL);
1492+
file = kmem_cache_alloc(file_cachep, GFP_TRACE);
14881493
if (!file)
14891494
return -ENOMEM;
14901495

@@ -1791,7 +1796,7 @@ __trace_remove_event_dirs(struct trace_array *tr)
17911796
list_del(&file->list);
17921797
debugfs_remove_recursive(file->dir);
17931798
remove_subsystem(file->system);
1794-
kfree(file);
1799+
kmem_cache_free(file_cachep, file);
17951800
}
17961801
}
17971802

@@ -1947,6 +1952,13 @@ int event_trace_del_tracer(struct trace_array *tr)
19471952
return 0;
19481953
}
19491954

1955+
static __init int event_trace_memsetup(void)
1956+
{
1957+
field_cachep = KMEM_CACHE(ftrace_event_field, SLAB_PANIC);
1958+
file_cachep = KMEM_CACHE(ftrace_event_file, SLAB_PANIC);
1959+
return 0;
1960+
}
1961+
19501962
static __init int event_trace_enable(void)
19511963
{
19521964
struct trace_array *tr = top_trace_array();
@@ -2021,6 +2033,7 @@ static __init int event_trace_init(void)
20212033

20222034
return 0;
20232035
}
2036+
early_initcall(event_trace_memsetup);
20242037
core_initcall(event_trace_enable);
20252038
fs_initcall(event_trace_init);
20262039

0 commit comments

Comments
 (0)