aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2009-04-23 23:27:05 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-04-24 00:08:38 -0400
commit334d4169a6592d3fcd863bbe822a8f6985ffa9af (patch)
tree3ac9c038304eaa69b06d9cac735fd62a8d6c47b3
parentc2518c4366f087ebc10b3919cb2461bbe4f42d0c (diff)
ring_buffer: compressed event header
RB_MAX_SMALL_DATA = 28bytes is too small for most tracers, it wastes an 'u32' to save the actually length for events which data size > 28. This fix uses compressed event header and enlarges RB_MAX_SMALL_DATA. [ Impact: saves about 0%-12.5%(depends on tracer) memory in ring_buffer ] Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> LKML-Reference: <49F13189.3090000@cn.fujitsu.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--include/linux/ring_buffer.h16
-rw-r--r--kernel/trace/ring_buffer.c83
2 files changed, 50 insertions, 49 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index fac8f1ac6f49..1c2f80911fbe 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -11,7 +11,7 @@ struct ring_buffer_iter;
11 * Don't refer to this struct directly, use functions below. 11 * Don't refer to this struct directly, use functions below.
12 */ 12 */
13struct ring_buffer_event { 13struct ring_buffer_event {
14 u32 type:2, len:3, time_delta:27; 14 u32 type_len:5, time_delta:27;
15 u32 array[]; 15 u32 array[];
16}; 16};
17 17
@@ -24,7 +24,8 @@ struct ring_buffer_event {
24 * size is variable depending on how much 24 * size is variable depending on how much
25 * padding is needed 25 * padding is needed
26 * If time_delta is non zero: 26 * If time_delta is non zero:
27 * everything else same as RINGBUF_TYPE_DATA 27 * array[0] holds the actual length
28 * size = 4 + length (bytes)
28 * 29 *
29 * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta 30 * @RINGBUF_TYPE_TIME_EXTEND: Extend the time delta
30 * array[0] = time delta (28 .. 59) 31 * array[0] = time delta (28 .. 59)
@@ -35,22 +36,23 @@ struct ring_buffer_event {
35 * array[1..2] = tv_sec 36 * array[1..2] = tv_sec
36 * size = 16 bytes 37 * size = 16 bytes
37 * 38 *
38 * @RINGBUF_TYPE_DATA: Data record 39 * <= @RINGBUF_TYPE_DATA_TYPE_LEN_MAX:
39 * If len is zero: 40 * Data record
41 * If type_len is zero:
40 * array[0] holds the actual length 42 * array[0] holds the actual length
41 * array[1..(length+3)/4] holds data 43 * array[1..(length+3)/4] holds data
42 * size = 4 + 4 + length (bytes) 44 * size = 4 + length (bytes)
43 * else 45 * else
44 * length = len << 2 46 * length = type_len << 2
45 * array[0..(length+3)/4-1] holds data 47 * array[0..(length+3)/4-1] holds data
46 * size = 4 + length (bytes) 48 * size = 4 + length (bytes)
47 */ 49 */
48enum ring_buffer_type { 50enum ring_buffer_type {
51 RINGBUF_TYPE_DATA_TYPE_LEN_MAX = 28,
49 RINGBUF_TYPE_PADDING, 52 RINGBUF_TYPE_PADDING,
50 RINGBUF_TYPE_TIME_EXTEND, 53 RINGBUF_TYPE_TIME_EXTEND,
51 /* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */ 54 /* FIXME: RINGBUF_TYPE_TIME_STAMP not implemented */
52 RINGBUF_TYPE_TIME_STAMP, 55 RINGBUF_TYPE_TIME_STAMP,
53 RINGBUF_TYPE_DATA,
54}; 56};
55 57
56unsigned ring_buffer_event_length(struct ring_buffer_event *event); 58unsigned ring_buffer_event_length(struct ring_buffer_event *event);
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 61dbdf21cd32..9692f100ec1a 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -28,8 +28,8 @@ int ring_buffer_print_entry_header(struct trace_seq *s)
28{ 28{
29 int ret; 29 int ret;
30 30
31 ret = trace_seq_printf(s, "\ttype : 2 bits\n"); 31 ret = trace_seq_printf(s, "# compressed entry header\n");
32 ret = trace_seq_printf(s, "\tlen : 3 bits\n"); 32 ret = trace_seq_printf(s, "\ttype_len : 5 bits\n");
33 ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n"); 33 ret = trace_seq_printf(s, "\ttime_delta : 27 bits\n");
34 ret = trace_seq_printf(s, "\tarray : 32 bits\n"); 34 ret = trace_seq_printf(s, "\tarray : 32 bits\n");
35 ret = trace_seq_printf(s, "\n"); 35 ret = trace_seq_printf(s, "\n");
@@ -37,8 +37,8 @@ int ring_buffer_print_entry_header(struct trace_seq *s)
37 RINGBUF_TYPE_PADDING); 37 RINGBUF_TYPE_PADDING);
38 ret = trace_seq_printf(s, "\ttime_extend : type == %d\n", 38 ret = trace_seq_printf(s, "\ttime_extend : type == %d\n",
39 RINGBUF_TYPE_TIME_EXTEND); 39 RINGBUF_TYPE_TIME_EXTEND);
40 ret = trace_seq_printf(s, "\tdata : type == %d\n", 40 ret = trace_seq_printf(s, "\tdata max type_len == %d\n",
41 RINGBUF_TYPE_DATA); 41 RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
42 42
43 return ret; 43 return ret;
44} 44}
@@ -204,7 +204,10 @@ EXPORT_SYMBOL_GPL(tracing_is_on);
204 204
205#define RB_EVNT_HDR_SIZE (offsetof(struct ring_buffer_event, array)) 205#define RB_EVNT_HDR_SIZE (offsetof(struct ring_buffer_event, array))
206#define RB_ALIGNMENT 4U 206#define RB_ALIGNMENT 4U
207#define RB_MAX_SMALL_DATA 28 207#define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
208
209/* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */
210#define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX
208 211
209enum { 212enum {
210 RB_LEN_TIME_EXTEND = 8, 213 RB_LEN_TIME_EXTEND = 8,
@@ -213,17 +216,18 @@ enum {
213 216
214static inline int rb_null_event(struct ring_buffer_event *event) 217static inline int rb_null_event(struct ring_buffer_event *event)
215{ 218{
216 return event->type == RINGBUF_TYPE_PADDING && event->time_delta == 0; 219 return event->type_len == RINGBUF_TYPE_PADDING
220 && event->time_delta == 0;
217} 221}
218 222
219static inline int rb_discarded_event(struct ring_buffer_event *event) 223static inline int rb_discarded_event(struct ring_buffer_event *event)
220{ 224{
221 return event->type == RINGBUF_TYPE_PADDING && event->time_delta; 225 return event->type_len == RINGBUF_TYPE_PADDING && event->time_delta;
222} 226}
223 227
224static void rb_event_set_padding(struct ring_buffer_event *event) 228static void rb_event_set_padding(struct ring_buffer_event *event)
225{ 229{
226 event->type = RINGBUF_TYPE_PADDING; 230 event->type_len = RINGBUF_TYPE_PADDING;
227 event->time_delta = 0; 231 event->time_delta = 0;
228} 232}
229 233
@@ -232,8 +236,8 @@ rb_event_data_length(struct ring_buffer_event *event)
232{ 236{
233 unsigned length; 237 unsigned length;
234 238
235 if (event->len) 239 if (event->type_len)
236 length = event->len * RB_ALIGNMENT; 240 length = event->type_len * RB_ALIGNMENT;
237 else 241 else
238 length = event->array[0]; 242 length = event->array[0];
239 return length + RB_EVNT_HDR_SIZE; 243 return length + RB_EVNT_HDR_SIZE;
@@ -243,12 +247,12 @@ rb_event_data_length(struct ring_buffer_event *event)
243static unsigned 247static unsigned
244rb_event_length(struct ring_buffer_event *event) 248rb_event_length(struct ring_buffer_event *event)
245{ 249{
246 switch (event->type) { 250 switch (event->type_len) {
247 case RINGBUF_TYPE_PADDING: 251 case RINGBUF_TYPE_PADDING:
248 if (rb_null_event(event)) 252 if (rb_null_event(event))
249 /* undefined */ 253 /* undefined */
250 return -1; 254 return -1;
251 return rb_event_data_length(event); 255 return event->array[0] + RB_EVNT_HDR_SIZE;
252 256
253 case RINGBUF_TYPE_TIME_EXTEND: 257 case RINGBUF_TYPE_TIME_EXTEND:
254 return RB_LEN_TIME_EXTEND; 258 return RB_LEN_TIME_EXTEND;
@@ -272,7 +276,7 @@ rb_event_length(struct ring_buffer_event *event)
272unsigned ring_buffer_event_length(struct ring_buffer_event *event) 276unsigned ring_buffer_event_length(struct ring_buffer_event *event)
273{ 277{
274 unsigned length = rb_event_length(event); 278 unsigned length = rb_event_length(event);
275 if (event->type != RINGBUF_TYPE_DATA) 279 if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
276 return length; 280 return length;
277 length -= RB_EVNT_HDR_SIZE; 281 length -= RB_EVNT_HDR_SIZE;
278 if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0])) 282 if (length > RB_MAX_SMALL_DATA + sizeof(event->array[0]))
@@ -285,9 +289,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_length);
285static void * 289static void *
286rb_event_data(struct ring_buffer_event *event) 290rb_event_data(struct ring_buffer_event *event)
287{ 291{
288 BUG_ON(event->type != RINGBUF_TYPE_DATA); 292 BUG_ON(event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX);
289 /* If length is in len field, then array[0] has the data */ 293 /* If length is in len field, then array[0] has the data */
290 if (event->len) 294 if (event->type_len)
291 return (void *)&event->array[0]; 295 return (void *)&event->array[0];
292 /* Otherwise length is in array[0] and array[1] has the data */ 296 /* Otherwise length is in array[0] and array[1] has the data */
293 return (void *)&event->array[1]; 297 return (void *)&event->array[1];
@@ -988,7 +992,7 @@ static void rb_update_overflow(struct ring_buffer_per_cpu *cpu_buffer)
988 if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) 992 if (RB_WARN_ON(cpu_buffer, rb_null_event(event)))
989 return; 993 return;
990 /* Only count data entries */ 994 /* Only count data entries */
991 if (event->type != RINGBUF_TYPE_DATA) 995 if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
992 continue; 996 continue;
993 cpu_buffer->overrun++; 997 cpu_buffer->overrun++;
994 cpu_buffer->entries--; 998 cpu_buffer->entries--;
@@ -1133,28 +1137,21 @@ static void
1133rb_update_event(struct ring_buffer_event *event, 1137rb_update_event(struct ring_buffer_event *event,
1134 unsigned type, unsigned length) 1138 unsigned type, unsigned length)
1135{ 1139{
1136 event->type = type; 1140 event->type_len = type;
1137 1141
1138 switch (type) { 1142 switch (type) {
1139 1143
1140 case RINGBUF_TYPE_PADDING: 1144 case RINGBUF_TYPE_PADDING:
1141 break;
1142
1143 case RINGBUF_TYPE_TIME_EXTEND: 1145 case RINGBUF_TYPE_TIME_EXTEND:
1144 event->len = DIV_ROUND_UP(RB_LEN_TIME_EXTEND, RB_ALIGNMENT);
1145 break;
1146
1147 case RINGBUF_TYPE_TIME_STAMP: 1146 case RINGBUF_TYPE_TIME_STAMP:
1148 event->len = DIV_ROUND_UP(RB_LEN_TIME_STAMP, RB_ALIGNMENT);
1149 break; 1147 break;
1150 1148
1151 case RINGBUF_TYPE_DATA: 1149 case 0:
1152 length -= RB_EVNT_HDR_SIZE; 1150 length -= RB_EVNT_HDR_SIZE;
1153 if (length > RB_MAX_SMALL_DATA) { 1151 if (length > RB_MAX_SMALL_DATA)
1154 event->len = 0;
1155 event->array[0] = length; 1152 event->array[0] = length;
1156 } else 1153 else
1157 event->len = DIV_ROUND_UP(length, RB_ALIGNMENT); 1154 event->type_len = DIV_ROUND_UP(length, RB_ALIGNMENT);
1158 break; 1155 break;
1159 default: 1156 default:
1160 BUG(); 1157 BUG();
@@ -1562,7 +1559,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)
1562 if (length > BUF_PAGE_SIZE) 1559 if (length > BUF_PAGE_SIZE)
1563 goto out; 1560 goto out;
1564 1561
1565 event = rb_reserve_next_event(cpu_buffer, RINGBUF_TYPE_DATA, length); 1562 event = rb_reserve_next_event(cpu_buffer, 0, length);
1566 if (!event) 1563 if (!event)
1567 goto out; 1564 goto out;
1568 1565
@@ -1634,7 +1631,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_unlock_commit);
1634 1631
1635static inline void rb_event_discard(struct ring_buffer_event *event) 1632static inline void rb_event_discard(struct ring_buffer_event *event)
1636{ 1633{
1637 event->type = RINGBUF_TYPE_PADDING; 1634 /* array[0] holds the actual length for the discarded event */
1635 event->array[0] = rb_event_data_length(event) - RB_EVNT_HDR_SIZE;
1636 event->type_len = RINGBUF_TYPE_PADDING;
1638 /* time delta must be non zero */ 1637 /* time delta must be non zero */
1639 if (!event->time_delta) 1638 if (!event->time_delta)
1640 event->time_delta = 1; 1639 event->time_delta = 1;
@@ -1786,8 +1785,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
1786 goto out; 1785 goto out;
1787 1786
1788 event_length = rb_calculate_event_length(length); 1787 event_length = rb_calculate_event_length(length);
1789 event = rb_reserve_next_event(cpu_buffer, 1788 event = rb_reserve_next_event(cpu_buffer, 0, event_length);
1790 RINGBUF_TYPE_DATA, event_length);
1791 if (!event) 1789 if (!event)
1792 goto out; 1790 goto out;
1793 1791
@@ -2035,7 +2033,7 @@ rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer,
2035{ 2033{
2036 u64 delta; 2034 u64 delta;
2037 2035
2038 switch (event->type) { 2036 switch (event->type_len) {
2039 case RINGBUF_TYPE_PADDING: 2037 case RINGBUF_TYPE_PADDING:
2040 return; 2038 return;
2041 2039
@@ -2066,7 +2064,7 @@ rb_update_iter_read_stamp(struct ring_buffer_iter *iter,
2066{ 2064{
2067 u64 delta; 2065 u64 delta;
2068 2066
2069 switch (event->type) { 2067 switch (event->type_len) {
2070 case RINGBUF_TYPE_PADDING: 2068 case RINGBUF_TYPE_PADDING:
2071 return; 2069 return;
2072 2070
@@ -2181,7 +2179,8 @@ static void rb_advance_reader(struct ring_buffer_per_cpu *cpu_buffer)
2181 2179
2182 event = rb_reader_event(cpu_buffer); 2180 event = rb_reader_event(cpu_buffer);
2183 2181
2184 if (event->type == RINGBUF_TYPE_DATA || rb_discarded_event(event)) 2182 if (event->type_len <= RINGBUF_TYPE_DATA_TYPE_LEN_MAX
2183 || rb_discarded_event(event))
2185 cpu_buffer->entries--; 2184 cpu_buffer->entries--;
2186 2185
2187 rb_update_read_stamp(cpu_buffer, event); 2186 rb_update_read_stamp(cpu_buffer, event);
@@ -2262,7 +2261,7 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
2262 2261
2263 event = rb_reader_event(cpu_buffer); 2262 event = rb_reader_event(cpu_buffer);
2264 2263
2265 switch (event->type) { 2264 switch (event->type_len) {
2266 case RINGBUF_TYPE_PADDING: 2265 case RINGBUF_TYPE_PADDING:
2267 if (rb_null_event(event)) 2266 if (rb_null_event(event))
2268 RB_WARN_ON(cpu_buffer, 1); 2267 RB_WARN_ON(cpu_buffer, 1);
@@ -2334,7 +2333,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
2334 2333
2335 event = rb_iter_head_event(iter); 2334 event = rb_iter_head_event(iter);
2336 2335
2337 switch (event->type) { 2336 switch (event->type_len) {
2338 case RINGBUF_TYPE_PADDING: 2337 case RINGBUF_TYPE_PADDING:
2339 if (rb_null_event(event)) { 2338 if (rb_null_event(event)) {
2340 rb_inc_iter(iter); 2339 rb_inc_iter(iter);
@@ -2393,7 +2392,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
2393 event = rb_buffer_peek(buffer, cpu, ts); 2392 event = rb_buffer_peek(buffer, cpu, ts);
2394 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); 2393 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
2395 2394
2396 if (event && event->type == RINGBUF_TYPE_PADDING) { 2395 if (event && event->type_len == RINGBUF_TYPE_PADDING) {
2397 cpu_relax(); 2396 cpu_relax();
2398 goto again; 2397 goto again;
2399 } 2398 }
@@ -2421,7 +2420,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
2421 event = rb_iter_peek(iter, ts); 2420 event = rb_iter_peek(iter, ts);
2422 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); 2421 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
2423 2422
2424 if (event && event->type == RINGBUF_TYPE_PADDING) { 2423 if (event && event->type_len == RINGBUF_TYPE_PADDING) {
2425 cpu_relax(); 2424 cpu_relax();
2426 goto again; 2425 goto again;
2427 } 2426 }
@@ -2466,7 +2465,7 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts)
2466 out: 2465 out:
2467 preempt_enable(); 2466 preempt_enable();
2468 2467
2469 if (event && event->type == RINGBUF_TYPE_PADDING) { 2468 if (event && event->type_len == RINGBUF_TYPE_PADDING) {
2470 cpu_relax(); 2469 cpu_relax();
2471 goto again; 2470 goto again;
2472 } 2471 }
@@ -2559,7 +2558,7 @@ ring_buffer_read(struct ring_buffer_iter *iter, u64 *ts)
2559 out: 2558 out:
2560 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); 2559 spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
2561 2560
2562 if (event && event->type == RINGBUF_TYPE_PADDING) { 2561 if (event && event->type_len == RINGBUF_TYPE_PADDING) {
2563 cpu_relax(); 2562 cpu_relax();
2564 goto again; 2563 goto again;
2565 } 2564 }
@@ -2766,7 +2765,7 @@ static void rb_remove_entries(struct ring_buffer_per_cpu *cpu_buffer,
2766 if (RB_WARN_ON(cpu_buffer, rb_null_event(event))) 2765 if (RB_WARN_ON(cpu_buffer, rb_null_event(event)))
2767 return; 2766 return;
2768 /* Only count data entries */ 2767 /* Only count data entries */
2769 if (event->type != RINGBUF_TYPE_DATA) 2768 if (event->type_len > RINGBUF_TYPE_DATA_TYPE_LEN_MAX)
2770 continue; 2769 continue;
2771 cpu_buffer->entries--; 2770 cpu_buffer->entries--;
2772 } 2771 }