Inline initial slice buffer allocation

pull/1274/head
Craig Tiller 10 years ago
parent 9a70c1aaf3
commit 721f362614
  1. 8
      include/grpc/support/slice_buffer.h
  2. 57
      src/core/support/slice_buffer.c
  3. 5
      src/core/transport/chttp2_transport.c

@ -40,6 +40,8 @@
extern "C" { extern "C" {
#endif #endif
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8
/* Represents an expandable array of slices, to be interpreted as a single item /* Represents an expandable array of slices, to be interpreted as a single item
TODO(ctiller): inline some small number of elements into the struct, to TODO(ctiller): inline some small number of elements into the struct, to
avoid per-call allocations */ avoid per-call allocations */
@ -52,6 +54,8 @@ typedef struct {
size_t capacity; size_t capacity;
/* the combined length of all slices in the array */ /* the combined length of all slices in the array */
size_t length; size_t length;
/* inlined elements to avoid allocations */
gpr_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
} gpr_slice_buffer; } gpr_slice_buffer;
/* initialize a slice buffer */ /* initialize a slice buffer */
@ -78,9 +82,11 @@ gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned len);
void gpr_slice_buffer_pop(gpr_slice_buffer *sb); void gpr_slice_buffer_pop(gpr_slice_buffer *sb);
/* clear a slice buffer, unref all elements */ /* clear a slice buffer, unref all elements */
void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb);
/* swap the contents of two slice buffers */
void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* GRPC_SUPPORT_SLICE_BUFFER_H */ #endif /* GRPC_SUPPORT_SLICE_BUFFER_H */

@ -38,21 +38,34 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
/* initial allocation size (# of slices) */ /* grow a buffer; requires GRPC_SLICE_BUFFER_INLINE_ELEMENTS > 1 */
#define INITIAL_CAPACITY 4
/* grow a buffer; requires INITIAL_CAPACITY > 1 */
#define GROW(x) (3 * (x) / 2) #define GROW(x) (3 * (x) / 2)
static void maybe_embiggen(gpr_slice_buffer *sb) {
if (sb->count == sb->capacity) {
sb->capacity = GROW(sb->capacity);
GPR_ASSERT(sb->capacity > sb->count);
if (sb->slices == sb->inlined) {
sb->slices = gpr_malloc(sb->capacity * sizeof(gpr_slice));
memcpy(sb->slices, sb->inlined, sb->count * sizeof(gpr_slice));
} else {
sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
}
}
}
void gpr_slice_buffer_init(gpr_slice_buffer *sb) { void gpr_slice_buffer_init(gpr_slice_buffer *sb) {
sb->count = 0; sb->count = 0;
sb->length = 0; sb->length = 0;
sb->capacity = INITIAL_CAPACITY; sb->capacity = GRPC_SLICE_BUFFER_INLINE_ELEMENTS;
sb->slices = gpr_malloc(sizeof(gpr_slice) * INITIAL_CAPACITY); sb->slices = sb->inlined;
} }
void gpr_slice_buffer_destroy(gpr_slice_buffer *sb) { void gpr_slice_buffer_destroy(gpr_slice_buffer *sb) {
gpr_slice_buffer_reset_and_unref(sb); gpr_slice_buffer_reset_and_unref(sb);
gpr_free(sb->slices); if (sb->slices != sb->inlined) {
gpr_free(sb->slices);
}
} }
gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned n) { gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned n) {
@ -71,11 +84,7 @@ gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned n) {
return out; return out;
add_new: add_new:
if (sb->count == sb->capacity) { maybe_embiggen(sb);
sb->capacity = GROW(sb->capacity);
GPR_ASSERT(sb->capacity > sb->count);
sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
}
back = &sb->slices[sb->count]; back = &sb->slices[sb->count];
sb->count++; sb->count++;
back->refcount = NULL; back->refcount = NULL;
@ -85,11 +94,7 @@ add_new:
size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, gpr_slice s) { size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, gpr_slice s) {
size_t out = sb->count; size_t out = sb->count;
if (out == sb->capacity) { maybe_embiggen(sb);
sb->capacity = GROW(sb->capacity);
GPR_ASSERT(sb->capacity > sb->count);
sb->slices = gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
}
sb->slices[out] = s; sb->slices[out] = s;
sb->length += GPR_SLICE_LENGTH(s); sb->length += GPR_SLICE_LENGTH(s);
sb->count = out + 1; sb->count = out + 1;
@ -116,12 +121,7 @@ void gpr_slice_buffer_add(gpr_slice_buffer *sb, gpr_slice s) {
memcpy(back->data.inlined.bytes + back->data.inlined.length, memcpy(back->data.inlined.bytes + back->data.inlined.length,
s.data.inlined.bytes, cp1); s.data.inlined.bytes, cp1);
back->data.inlined.length = GPR_SLICE_INLINED_SIZE; back->data.inlined.length = GPR_SLICE_INLINED_SIZE;
if (n == sb->capacity) { maybe_embiggen(sb);
sb->capacity = GROW(sb->capacity);
GPR_ASSERT(sb->capacity > sb->count);
sb->slices =
gpr_realloc(sb->slices, sb->capacity * sizeof(gpr_slice));
}
back = &sb->slices[n]; back = &sb->slices[n];
sb->count = n + 1; sb->count = n + 1;
back->refcount = NULL; back->refcount = NULL;
@ -160,3 +160,16 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) {
sb->count = 0; sb->count = 0;
sb->length = 0; 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;
if (a->slices == b->inlined) {
a->slices = a->inlined;
}
if (b->slices == a->inlined) {
b->slices = b->inlined;
}
}

@ -834,13 +834,10 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id,
static int prepare_write(transport *t) { static int prepare_write(transport *t) {
stream *s; stream *s;
gpr_slice_buffer tempbuf;
gpr_uint32 window_delta; gpr_uint32 window_delta;
/* simple writes are queued to qbuf, and flushed here */ /* simple writes are queued to qbuf, and flushed here */
tempbuf = t->qbuf; gpr_slice_buffer_swap(&t->qbuf, &t->outbuf);
t->qbuf = t->outbuf;
t->outbuf = tempbuf;
GPR_ASSERT(t->qbuf.count == 0); GPR_ASSERT(t->qbuf.count == 0);
if (t->dirtied_local_settings && !t->sent_local_settings) { if (t->dirtied_local_settings && !t->sent_local_settings) {

Loading…
Cancel
Save