From 40158ed8560c9092c0f16c223f947527454e7f8a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 28 Apr 2015 13:03:40 -0700 Subject: [PATCH 1/3] Optimize slice_buffer_swap --- src/core/support/slice_buffer.c | 39 ++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 3b1daa07c54..1992eeef8b5 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -161,15 +161,38 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) { sb->length = 0; } -void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) { - gpr_slice_buffer temp = *a; - *a = *b; - *b = temp; +#define SWAP(type, a, b) \ + do { \ + type x = a; \ + a = b; \ + b = x; \ + } while (0) - if (a->slices == b->inlined) { +void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) { + SWAP(size_t, a->count, b->count); + SWAP(size_t, a->capacity, b->capacity); + SWAP(size_t, a->length, b->length); + + if (a->slices == a->inlined) { + if (b->slices == b->inlined) { + /* swap contents of inlined buffer */ + gpr_slice temp[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; + memcpy(temp, a->slices, b->count * sizeof(gpr_slice)); + memcpy(a->slices, b->slices, a->count * sizeof(gpr_slice)); + memcpy(b->slices, temp, b->count * sizeof(gpr_slice)); + } else { + /* a is inlined, b is not - copy a inlined into b, fix pointers */ + a->slices = b->slices; + b->slices = b->inlined; + memcpy(b->slices, a->inlined, b->count * sizeof(gpr_slice)); + } + } else if (b->slices == b->inlined) { + /* b is inlined, a is not - copy b inlined int a, fix pointers */ + b->slices = a->slices; a->slices = a->inlined; - } - if (b->slices == a->inlined) { - b->slices = b->inlined; + memcpy(a->slices, b->inlined, a->count * sizeof(gpr_slice)); + } else { + /* no inlining: easy swap */ + SWAP(gpr_slice *, a->slices, b->slices); } } From bae41c847f084fe64b5920f09d7ffbac579c507a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 28 Apr 2015 13:22:25 -0700 Subject: [PATCH 2/3] Promote SWAP to GPR_SWAP --- include/grpc/support/useful.h | 7 +++++++ src/core/support/slice_buffer.c | 16 +++++----------- src/core/surface/call.c | 11 ++--------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/grpc/support/useful.h b/include/grpc/support/useful.h index 979f3d026b3..e1ce0455c6a 100644 --- a/include/grpc/support/useful.h +++ b/include/grpc/support/useful.h @@ -45,4 +45,11 @@ #define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array))) +#define GPR_SWAP(type, a, b) \ + do { \ + type x = a; \ + a = b; \ + b = x; \ + } while (0) + #endif /* GRPC_SUPPORT_USEFUL_H */ diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 1992eeef8b5..91b5d8c98b2 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -37,6 +37,7 @@ #include #include +#include /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */ #define GROW(x) (3 * (x) / 2) @@ -161,17 +162,10 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) { sb->length = 0; } -#define SWAP(type, a, b) \ - do { \ - type x = a; \ - a = b; \ - b = x; \ - } while (0) - void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) { - SWAP(size_t, a->count, b->count); - SWAP(size_t, a->capacity, b->capacity); - SWAP(size_t, a->length, b->length); + GPR_SWAP(size_t, a->count, b->count); + GPR_SWAP(size_t, a->capacity, b->capacity); + GPR_SWAP(size_t, a->length, b->length); if (a->slices == a->inlined) { if (b->slices == b->inlined) { @@ -193,6 +187,6 @@ void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b) { memcpy(a->slices, b->inlined, a->count * sizeof(gpr_slice)); } else { /* no inlining: easy swap */ - SWAP(gpr_slice *, a->slices, b->slices); + GPR_SWAP(gpr_slice *, a->slices, b->slices); } } diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f358eb546a9..d21bfaa5923 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -238,13 +238,6 @@ struct grpc_call { #define CALL_FROM_TOP_ELEM(top_elem) \ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem)) -#define SWAP(type, x, y) \ - do { \ - type temp = x; \ - x = y; \ - y = temp; \ - } while (0) - static void do_nothing(void *ignored, grpc_op_error also_ignored) {} static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline); static void call_on_done_recv(void *call, int success); @@ -575,12 +568,12 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, call->request_data[GRPC_IOREQ_RECV_STATUS_DETAILS]); break; case GRPC_IOREQ_RECV_INITIAL_METADATA: - SWAP(grpc_metadata_array, call->buffered_metadata[0], + GPR_SWAP(grpc_metadata_array, call->buffered_metadata[0], *call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA] .recv_metadata); break; case GRPC_IOREQ_RECV_TRAILING_METADATA: - SWAP(grpc_metadata_array, call->buffered_metadata[1], + GPR_SWAP(grpc_metadata_array, call->buffered_metadata[1], *call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA] .recv_metadata); break; From 7e61d52d03954b98a1ea2645b2c43d6dfe655bba Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 28 Apr 2015 13:39:21 -0700 Subject: [PATCH 3/3] Faster stream_op_buffer swap --- src/core/transport/stream_op.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/core/transport/stream_op.c b/src/core/transport/stream_op.c index e1a75adcb6e..8996ecac357 100644 --- a/src/core/transport/stream_op.c +++ b/src/core/transport/stream_op.c @@ -59,15 +59,30 @@ void grpc_sopb_reset(grpc_stream_op_buffer *sopb) { } void grpc_sopb_swap(grpc_stream_op_buffer *a, grpc_stream_op_buffer *b) { - grpc_stream_op_buffer temp = *a; - *a = *b; - *b = temp; - - if (a->ops == b->inlined_ops) { + GPR_SWAP(size_t, a->nops, b->nops); + GPR_SWAP(size_t, a->capacity, b->capacity); + + if (a->ops == a->inlined_ops) { + if (b->ops == b->inlined_ops) { + /* swap contents of inlined buffer */ + gpr_slice temp[GRPC_SOPB_INLINE_ELEMENTS]; + memcpy(temp, a->ops, b->nops * sizeof(grpc_stream_op)); + memcpy(a->ops, b->ops, a->nops * sizeof(grpc_stream_op)); + memcpy(b->ops, temp, b->nops * sizeof(grpc_stream_op)); + } else { + /* a is inlined, b is not - copy a inlined into b, fix pointers */ + a->ops = b->ops; + b->ops = b->inlined_ops; + memcpy(b->ops, a->inlined_ops, b->nops * sizeof(grpc_stream_op)); + } + } else if (b->ops == b->inlined_ops) { + /* b is inlined, a is not - copy b inlined int a, fix pointers */ + b->ops = a->ops; a->ops = a->inlined_ops; - } - if (b->ops == a->inlined_ops) { - b->ops = b->inlined_ops; + memcpy(a->ops, b->inlined_ops, a->nops * sizeof(grpc_stream_op)); + } else { + /* no inlining: easy swap */ + GPR_SWAP(grpc_stream_op *, a->ops, b->ops); } }