aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar alex <alex@thoughtmachine.net>2016-03-22 17:49:56 +0000
committerGravatar alex <alex@thoughtmachine.net>2016-03-22 17:49:56 +0000
commitce379382552e118a499db95c0d311849557d0227 (patch)
treeff3be6cf171762a5b29563c22b23c7eabecc12e4 /src
parent04961a09220bdfb5665d8017af0a698af9f4c422 (diff)
Make grpc-python ByteBuffer.bytes() linear cost.
Currently ByteBuffer.bytes() reads from the underlying grpc byte_buffer a slice at a time, and appends each to a Python string (bytes). In Python strings are immutable, so appending creates a new string by copying the previous data. This means the current implementation is quadratic. The effect is very noticeable when messages have repeated (or large) string fields. We traced execution between two services and observed that when the payload size approached 600kb, the receiving service took ~10s at full CPU to read a response that had taken fractions of a second the send over the network. This commit changes ByteBuffer.bytes() to use an intermediate bytearray, instead of strings, for the in-progress bytes. Once all slices are read, the buffer is converted to a string.
Diffstat (limited to 'src')
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index 851389a261..6ecdcf7222 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -254,7 +254,7 @@ cdef class ByteBuffer:
if self.c_byte_buffer != NULL:
with nogil:
grpc_byte_buffer_reader_init(&reader, self.c_byte_buffer)
- result = b""
+ result = bytearray()
with nogil:
while grpc_byte_buffer_reader_next(&reader, &data_slice):
data_slice_pointer = gpr_slice_start_ptr(data_slice)
@@ -263,7 +263,7 @@ cdef class ByteBuffer:
result += (<char *>data_slice_pointer)[:data_slice_length]
with nogil:
grpc_byte_buffer_reader_destroy(&reader)
- return result
+ return bytes(result)
else:
return None