Skip to content

Commit

Permalink
tracing: Shrink max latency ringbuffer if unnecessary
Browse files Browse the repository at this point in the history
Documentation/trace/ftrace.txt says

  buffer_size_kb:

        This sets or displays the number of kilobytes each CPU
        buffer can hold. The tracer buffers are the same size
        for each CPU. The displayed number is the size of the
        CPU buffer and not total size of all buffers. The
        trace buffers are allocated in pages (blocks of memory
        that the kernel uses for allocation, usually 4 KB in size).
        If the last page allocated has room for more bytes
        than requested, the rest of the page will be used,
        making the actual allocation bigger than requested.
        ( Note, the size may not be a multiple of the page size
          due to buffer management overhead. )

        This can only be updated when the current_tracer
        is set to "nop".

But it's incorrect. currently total memory consumption is
'buffer_size_kb x CPUs x 2'.

Why two times difference is there? because ftrace implicitly allocate
the buffer for max latency too.

That makes sad result when admin want to use large buffer. (If admin
want full logging and makes detail analysis). example, If admin
have 24 CPUs machine and write 200MB to buffer_size_kb, the system
consume ~10GB memory (200MB x 24 x 2). umm.. 5GB memory waste is
usually unacceptable.

Fortunatelly, almost all users don't use max latency feature.
The max latency buffer can be disabled easily.

This patch shrink buffer size of the max latency buffer if
unnecessary.

Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
LKML-Reference: <20100701104554.DA2D.A69D9226@jp.fujitsu.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
  • Loading branch information
KOSAKI Motohiro authored and Steven Rostedt committed Jul 21, 2010
1 parent bc289ae commit ef710e1
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 6 deletions.
38 changes: 32 additions & 6 deletions kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,10 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
return;

WARN_ON_ONCE(!irqs_disabled());
if (!current_trace->use_max_tr) {
WARN_ON_ONCE(1);
return;
}
arch_spin_lock(&ftrace_max_lock);

tr->buffer = max_tr.buffer;
Expand All @@ -686,6 +690,11 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
return;

WARN_ON_ONCE(!irqs_disabled());
if (!current_trace->use_max_tr) {
WARN_ON_ONCE(1);
return;
}

arch_spin_lock(&ftrace_max_lock);

ftrace_disable_cpu();
Expand Down Expand Up @@ -2801,6 +2810,9 @@ static int tracing_resize_ring_buffer(unsigned long size)
if (ret < 0)
return ret;

if (!current_trace->use_max_tr)
goto out;

ret = ring_buffer_resize(max_tr.buffer, size);
if (ret < 0) {
int r;
Expand Down Expand Up @@ -2828,11 +2840,14 @@ static int tracing_resize_ring_buffer(unsigned long size)
return ret;
}

max_tr.entries = size;
out:
global_trace.entries = size;

return ret;
}


/**
* tracing_update_buffers - used by tracing facility to expand ring buffers
*
Expand Down Expand Up @@ -2893,12 +2908,26 @@ static int tracing_set_tracer(const char *buf)
trace_branch_disable();
if (current_trace && current_trace->reset)
current_trace->reset(tr);

if (current_trace && current_trace->use_max_tr) {
/*
* We don't free the ring buffer. instead, resize it because
* The max_tr ring buffer has some state (e.g. ring->clock) and
* we want preserve it.
*/
ring_buffer_resize(max_tr.buffer, 1);
max_tr.entries = 1;
}
destroy_trace_option_files(topts);

current_trace = t;

topts = create_trace_option_files(current_trace);
if (current_trace->use_max_tr) {
ret = ring_buffer_resize(max_tr.buffer, global_trace.entries);
if (ret < 0)
goto out;
max_tr.entries = global_trace.entries;
}

if (t->init) {
ret = tracer_init(t, tr);
Expand Down Expand Up @@ -3480,7 +3509,6 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
}

tracing_start();
max_tr.entries = global_trace.entries;
mutex_unlock(&trace_types_lock);

return cnt;
Expand Down Expand Up @@ -4578,16 +4606,14 @@ __init static int tracer_alloc_buffers(void)


#ifdef CONFIG_TRACER_MAX_TRACE
max_tr.buffer = ring_buffer_alloc(ring_buf_size,
TRACE_BUFFER_FLAGS);
max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS);
if (!max_tr.buffer) {
printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
WARN_ON(1);
ring_buffer_free(global_trace.buffer);
goto out_free_cpumask;
}
max_tr.entries = ring_buffer_size(max_tr.buffer);
WARN_ON(max_tr.entries != global_trace.entries);
max_tr.entries = 1;
#endif

/* Allocate the first page for all buffers */
Expand Down
1 change: 1 addition & 0 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ struct tracer {
struct tracer *next;
int print_max;
struct tracer_flags *flags;
int use_max_tr;
};


Expand Down
3 changes: 3 additions & 0 deletions kernel/trace/trace_irqsoff.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ static struct tracer irqsoff_tracer __read_mostly =
#endif
.open = irqsoff_trace_open,
.close = irqsoff_trace_close,
.use_max_tr = 1,
};
# define register_irqsoff(trace) register_tracer(&trace)
#else
Expand Down Expand Up @@ -681,6 +682,7 @@ static struct tracer preemptoff_tracer __read_mostly =
#endif
.open = irqsoff_trace_open,
.close = irqsoff_trace_close,
.use_max_tr = 1,
};
# define register_preemptoff(trace) register_tracer(&trace)
#else
Expand Down Expand Up @@ -715,6 +717,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
#endif
.open = irqsoff_trace_open,
.close = irqsoff_trace_close,
.use_max_tr = 1,
};

# define register_preemptirqsoff(trace) register_tracer(&trace)
Expand Down
2 changes: 2 additions & 0 deletions kernel/trace/trace_sched_wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ static struct tracer wakeup_tracer __read_mostly =
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_wakeup,
#endif
.use_max_tr = 1,
};

static struct tracer wakeup_rt_tracer __read_mostly =
Expand All @@ -396,6 +397,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_wakeup,
#endif
.use_max_tr = 1,
};

__init static int init_wakeup_tracer(void)
Expand Down

0 comments on commit ef710e1

Please sign in to comment.