mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
300 lines
8.1 KiB
Python
300 lines
8.1 KiB
Python
"""Benchmarks for assigning large NumPy data to protobuf fields."""
|
|
|
|
from collections.abc import Callable
|
|
import functools
|
|
import sys
|
|
|
|
import google_benchmark
|
|
import numpy as np
|
|
|
|
from google.protobuf import unittest_pb2
|
|
|
|
|
|
@functools.cache
|
|
def make_array(num_bytes: int):
|
|
return np.zeros(shape=(num_bytes,), dtype=np.uint8)
|
|
|
|
|
|
def benchmark(
|
|
func: Callable[[google_benchmark.State], None],
|
|
) -> Callable[[google_benchmark.State], None]:
|
|
"""Decorates a function for benchmarking."""
|
|
|
|
@google_benchmark.register
|
|
@google_benchmark.option.unit(google_benchmark.kMillisecond)
|
|
@google_benchmark.option.arg_names(['num_bytes'])
|
|
@google_benchmark.option.arg(1024 * 1024 * 20)
|
|
@google_benchmark.option.arg(1024 * 1024 * 100)
|
|
@functools.wraps(func)
|
|
def wrapper(state: google_benchmark.State) -> None:
|
|
func(state)
|
|
state.bytes_processed = state.iterations * state.range(0)
|
|
|
|
return wrapper
|
|
|
|
|
|
@benchmark
|
|
def bench_build_message_via_slice(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
while state:
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.repeated_int32[:] = arr
|
|
|
|
|
|
@benchmark
|
|
def bench_build_message(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
while state:
|
|
_ = unittest_pb2.TestAllTypes(repeated_int32=arr)
|
|
|
|
|
|
@benchmark
|
|
def bench_build_message_nested_via_slice(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
while state:
|
|
msg = unittest_pb2.NestedTestAllTypes()
|
|
msg.payload.repeated_int32[:] = arr
|
|
|
|
|
|
@benchmark
|
|
def bench_build_nested_message_dict(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
while state:
|
|
_ = unittest_pb2.NestedTestAllTypes(payload=dict(repeated_int32=arr))
|
|
|
|
|
|
@benchmark
|
|
def bench_build_nested_message_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
while state:
|
|
_ = unittest_pb2.NestedTestAllTypes(
|
|
payload=unittest_pb2.TestAllTypes(repeated_int32=arr)
|
|
)
|
|
|
|
|
|
@benchmark
|
|
def bench_build_nested_message_cord(state: google_benchmark.State):
|
|
chunk_size = state.range(0) // 1000
|
|
strings = ['a' * chunk_size] * 1000
|
|
while state:
|
|
_ = unittest_pb2.NestedTestAllTypes(
|
|
payload=unittest_pb2.TestAllTypes(repeated_cord=strings)
|
|
)
|
|
|
|
|
|
@benchmark
|
|
def bench_build_nested_message_string_piece(state: google_benchmark.State):
|
|
chunk_size = state.range(0) // 1000
|
|
strings = ['a' * chunk_size] * 1000
|
|
while state:
|
|
_ = unittest_pb2.NestedTestAllTypes(
|
|
payload=unittest_pb2.TestAllTypes(repeated_string_piece=strings)
|
|
)
|
|
|
|
|
|
@benchmark
|
|
def bench_build_nested_message_nested_message(state: google_benchmark.State):
|
|
subs = [unittest_pb2.TestAllTypes.NestedMessage(bb=123)] * (
|
|
state.range(0) // 8
|
|
)
|
|
while state:
|
|
_ = unittest_pb2.NestedTestAllTypes(
|
|
payload=unittest_pb2.TestAllTypes(repeated_nested_message=subs)
|
|
)
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_repeated_float(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.float32)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg_source = unittest_pb2.TestAllTypes()
|
|
msg_source.repeated_float.extend(arr)
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_float[:] = msg_source.repeated_float
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_repeated_int64_to_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg_source = unittest_pb2.TestAllTypes()
|
|
msg_source.repeated_int64.extend(arr)
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_int32[:] = msg_source.repeated_int64
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_repeated_double_to_float(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.float64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg_source = unittest_pb2.TestAllTypes()
|
|
msg_source.repeated_double.extend(arr)
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_float[:] = msg_source.repeated_double
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_numpy_int64_to_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_int32[:] = arr
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_numpy_double_to_float(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.float64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_float[:] = arr
|
|
|
|
|
|
@benchmark
|
|
def bench_extend_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_int32.extend(arr)
|
|
|
|
|
|
@benchmark
|
|
def bench_decode_from_bytes(state: google_benchmark.State):
|
|
arr = make_array(state.range(0))
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.optional_bytes = memoryview(arr)
|
|
msg_bytes = msg.SerializeToString()
|
|
while state:
|
|
_ = unittest_pb2.TestAllTypes.FromString(msg_bytes)
|
|
|
|
|
|
@benchmark
|
|
def bench_decode_from_memoryview(state: google_benchmark.State):
|
|
arr = make_array(state.range(0))
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.optional_bytes = memoryview(arr)
|
|
msg_bytes = memoryview(msg.SerializeToString())
|
|
while state:
|
|
_ = unittest_pb2.TestAllTypes.FromString(msg_bytes)
|
|
|
|
|
|
@benchmark
|
|
def bench_encode_into_bytes(state: google_benchmark.State):
|
|
arr = make_array(state.range(0))
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.optional_bytes = memoryview(arr)
|
|
while state:
|
|
_ = msg.SerializeToString()
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
msg.repeated_int32[:] = arr
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_extend_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.repeated_int32[:] = arr
|
|
while state:
|
|
msg.repeated_int32[len(arr) :] = arr
|
|
state.pause_timing()
|
|
msg.repeated_int32[:] = arr
|
|
state.resume_timing()
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_slice_int32(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int32)
|
|
half_arr = arr[: len(arr) // 2]
|
|
msg = unittest_pb2.TestAllTypes()
|
|
msg.repeated_int32.extend(arr)
|
|
while state:
|
|
msg.repeated_int32[::2] = half_arr
|
|
|
|
|
|
@benchmark
|
|
def bench_extend_int64(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.int64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_int64.extend(arr)
|
|
|
|
|
|
@benchmark
|
|
def bench_extend_float(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.float32)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_float.extend(arr)
|
|
|
|
|
|
@benchmark
|
|
def bench_extend_double(state: google_benchmark.State):
|
|
arr = make_array(state.range(0)).view(dtype=np.float64)
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.repeated_double.extend(arr)
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_bytes(state: google_benchmark.State):
|
|
arr = make_array(state.range(0))
|
|
msg = unittest_pb2.TestAllTypes()
|
|
arr_bytes = arr.tobytes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.optional_bytes = arr_bytes
|
|
|
|
|
|
@benchmark
|
|
def bench_assign_bytes_with_conversion(state: google_benchmark.State):
|
|
arr = make_array(state.range(0))
|
|
msg = unittest_pb2.TestAllTypes()
|
|
while state:
|
|
state.pause_timing()
|
|
msg.Clear()
|
|
state.resume_timing()
|
|
msg.optional_bytes = memoryview(arr)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if any(arg.startswith('--benchmark_filter') for arg in sys.argv):
|
|
google_benchmark.main()
|
|
else:
|
|
print('No benchmark filter specified. Skipping benchmarks.')
|