blob: 6413648028b431718db874bb6d74de8eb24fad66 [file]
"""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.')