xref: /aosp_15_r20/external/protobuf/benchmarks/python/py_benchmark.py (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Workerfrom __future__ import print_function
2*1b3f573fSAndroid Build Coastguard Workerimport sys
3*1b3f573fSAndroid Build Coastguard Workerimport os
4*1b3f573fSAndroid Build Coastguard Workerimport timeit
5*1b3f573fSAndroid Build Coastguard Workerimport math
6*1b3f573fSAndroid Build Coastguard Workerimport argparse
7*1b3f573fSAndroid Build Coastguard Workerimport fnmatch
8*1b3f573fSAndroid Build Coastguard Workerimport json
9*1b3f573fSAndroid Build Coastguard Worker
10*1b3f573fSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(description="Python protobuf benchmark")
11*1b3f573fSAndroid Build Coastguard Workerparser.add_argument("data_files", metavar="dataFile", nargs="+",
12*1b3f573fSAndroid Build Coastguard Worker                    help="testing data files.")
13*1b3f573fSAndroid Build Coastguard Workerparser.add_argument("--json", action="store_const", dest="json",
14*1b3f573fSAndroid Build Coastguard Worker                    const="yes", default="no",
15*1b3f573fSAndroid Build Coastguard Worker                    help="Whether to output json results")
16*1b3f573fSAndroid Build Coastguard Workerparser.add_argument("--behavior_prefix", dest="behavior_prefix",
17*1b3f573fSAndroid Build Coastguard Worker                    help="The output json format's behavior's name's prefix",
18*1b3f573fSAndroid Build Coastguard Worker                    default="")
19*1b3f573fSAndroid Build Coastguard Worker# BEGIN CPP GENERATED MESSAGE
20*1b3f573fSAndroid Build Coastguard Workerparser.add_argument("--cpp_generated", action="store_const",
21*1b3f573fSAndroid Build Coastguard Worker                    dest="cpp_generated", const="yes", default="no",
22*1b3f573fSAndroid Build Coastguard Worker                    help="Whether to link generated code library")
23*1b3f573fSAndroid Build Coastguard Worker# END CPP GENERATED MESSAGE
24*1b3f573fSAndroid Build Coastguard Workerargs = parser.parse_args()
25*1b3f573fSAndroid Build Coastguard Worker# BEGIN CPP GENERATED MESSAGE
26*1b3f573fSAndroid Build Coastguard Worker# CPP generated code must be linked before importing the generated Python code
27*1b3f573fSAndroid Build Coastguard Worker# for the descriptor can be found in the pool
28*1b3f573fSAndroid Build Coastguard Workerif args.cpp_generated != "no":
29*1b3f573fSAndroid Build Coastguard Worker  sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/.libs" )
30*1b3f573fSAndroid Build Coastguard Worker  import libbenchmark_messages
31*1b3f573fSAndroid Build Coastguard Worker  sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/tmp" )
32*1b3f573fSAndroid Build Coastguard Worker# END CPP GENERATED MESSAGE
33*1b3f573fSAndroid Build Coastguard Worker
34*1b3f573fSAndroid Build Coastguard Worker
35*1b3f573fSAndroid Build Coastguard Workerimport datasets.google_message1.proto2.benchmark_message1_proto2_pb2 as benchmark_message1_proto2_pb2
36*1b3f573fSAndroid Build Coastguard Workerimport datasets.google_message1.proto3.benchmark_message1_proto3_pb2 as benchmark_message1_proto3_pb2
37*1b3f573fSAndroid Build Coastguard Workerimport datasets.google_message2.benchmark_message2_pb2 as benchmark_message2_pb2
38*1b3f573fSAndroid Build Coastguard Workerimport datasets.google_message3.benchmark_message3_pb2 as benchmark_message3_pb2
39*1b3f573fSAndroid Build Coastguard Workerimport datasets.google_message4.benchmark_message4_pb2 as benchmark_message4_pb2
40*1b3f573fSAndroid Build Coastguard Workerimport benchmarks_pb2 as benchmarks_pb2
41*1b3f573fSAndroid Build Coastguard Worker
42*1b3f573fSAndroid Build Coastguard Worker
43*1b3f573fSAndroid Build Coastguard Workerdef run_one_test(filename):
44*1b3f573fSAndroid Build Coastguard Worker  data = open(filename, "rb").read()
45*1b3f573fSAndroid Build Coastguard Worker  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
46*1b3f573fSAndroid Build Coastguard Worker  benchmark_dataset.ParseFromString(data)
47*1b3f573fSAndroid Build Coastguard Worker  total_bytes = 0
48*1b3f573fSAndroid Build Coastguard Worker  for payload in benchmark_dataset.payload:
49*1b3f573fSAndroid Build Coastguard Worker    total_bytes += len(payload)
50*1b3f573fSAndroid Build Coastguard Worker  benchmark_util = Benchmark(full_iteration=len(benchmark_dataset.payload),
51*1b3f573fSAndroid Build Coastguard Worker                             module="py_benchmark",
52*1b3f573fSAndroid Build Coastguard Worker                             setup_method="init",
53*1b3f573fSAndroid Build Coastguard Worker                             total_bytes=total_bytes)
54*1b3f573fSAndroid Build Coastguard Worker  result={}
55*1b3f573fSAndroid Build Coastguard Worker  result["filename"] =  filename
56*1b3f573fSAndroid Build Coastguard Worker  result["message_name"] =  benchmark_dataset.message_name
57*1b3f573fSAndroid Build Coastguard Worker  result["benchmarks"] = {}
58*1b3f573fSAndroid Build Coastguard Worker  benchmark_util.set_test_method("parse_from_benchmark")
59*1b3f573fSAndroid Build Coastguard Worker  result["benchmarks"][args.behavior_prefix + "_parse_from_benchmark"] = \
60*1b3f573fSAndroid Build Coastguard Worker    benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename))
61*1b3f573fSAndroid Build Coastguard Worker  benchmark_util.set_test_method("serialize_to_benchmark")
62*1b3f573fSAndroid Build Coastguard Worker  result["benchmarks"][args.behavior_prefix + "_serialize_to_benchmark"] = \
63*1b3f573fSAndroid Build Coastguard Worker    benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename))
64*1b3f573fSAndroid Build Coastguard Worker  return result
65*1b3f573fSAndroid Build Coastguard Worker
66*1b3f573fSAndroid Build Coastguard Worker
67*1b3f573fSAndroid Build Coastguard Workerdef init(filename):
68*1b3f573fSAndroid Build Coastguard Worker  global benchmark_dataset, message_class, message_list, counter, total_bytes
69*1b3f573fSAndroid Build Coastguard Worker  message_list=[]
70*1b3f573fSAndroid Build Coastguard Worker  counter = 0
71*1b3f573fSAndroid Build Coastguard Worker  total_bytes = 0
72*1b3f573fSAndroid Build Coastguard Worker  data = open(filename, "rb").read()
73*1b3f573fSAndroid Build Coastguard Worker  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
74*1b3f573fSAndroid Build Coastguard Worker  benchmark_dataset.ParseFromString(data)
75*1b3f573fSAndroid Build Coastguard Worker
76*1b3f573fSAndroid Build Coastguard Worker  if benchmark_dataset.message_name == "benchmarks.proto3.GoogleMessage1":
77*1b3f573fSAndroid Build Coastguard Worker    message_class = benchmark_message1_proto3_pb2.GoogleMessage1
78*1b3f573fSAndroid Build Coastguard Worker  elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage1":
79*1b3f573fSAndroid Build Coastguard Worker    message_class = benchmark_message1_proto2_pb2.GoogleMessage1
80*1b3f573fSAndroid Build Coastguard Worker  elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage2":
81*1b3f573fSAndroid Build Coastguard Worker    message_class = benchmark_message2_pb2.GoogleMessage2
82*1b3f573fSAndroid Build Coastguard Worker  elif benchmark_dataset.message_name == "benchmarks.google_message3.GoogleMessage3":
83*1b3f573fSAndroid Build Coastguard Worker    message_class = benchmark_message3_pb2.GoogleMessage3
84*1b3f573fSAndroid Build Coastguard Worker  elif benchmark_dataset.message_name == "benchmarks.google_message4.GoogleMessage4":
85*1b3f573fSAndroid Build Coastguard Worker    message_class = benchmark_message4_pb2.GoogleMessage4
86*1b3f573fSAndroid Build Coastguard Worker  else:
87*1b3f573fSAndroid Build Coastguard Worker    raise IOError("Message %s not found!" % (benchmark_dataset.message_name))
88*1b3f573fSAndroid Build Coastguard Worker
89*1b3f573fSAndroid Build Coastguard Worker  for one_payload in benchmark_dataset.payload:
90*1b3f573fSAndroid Build Coastguard Worker    temp = message_class()
91*1b3f573fSAndroid Build Coastguard Worker    temp.ParseFromString(one_payload)
92*1b3f573fSAndroid Build Coastguard Worker    message_list.append(temp)
93*1b3f573fSAndroid Build Coastguard Worker    total_bytes += len(one_payload)
94*1b3f573fSAndroid Build Coastguard Worker
95*1b3f573fSAndroid Build Coastguard Worker
96*1b3f573fSAndroid Build Coastguard Workerdef parse_from_benchmark():
97*1b3f573fSAndroid Build Coastguard Worker  global counter, message_class, benchmark_dataset
98*1b3f573fSAndroid Build Coastguard Worker  m = message_class().ParseFromString(benchmark_dataset.payload[counter % len(benchmark_dataset.payload)])
99*1b3f573fSAndroid Build Coastguard Worker  counter = counter + 1
100*1b3f573fSAndroid Build Coastguard Worker
101*1b3f573fSAndroid Build Coastguard Worker
102*1b3f573fSAndroid Build Coastguard Workerdef serialize_to_benchmark():
103*1b3f573fSAndroid Build Coastguard Worker  global counter, message_list, message_class
104*1b3f573fSAndroid Build Coastguard Worker  s = message_list[counter % len(benchmark_dataset.payload)].SerializeToString()
105*1b3f573fSAndroid Build Coastguard Worker  counter = counter + 1
106*1b3f573fSAndroid Build Coastguard Worker
107*1b3f573fSAndroid Build Coastguard Worker
108*1b3f573fSAndroid Build Coastguard Workerclass Benchmark:
109*1b3f573fSAndroid Build Coastguard Worker  def __init__(self, module=None, test_method=None,
110*1b3f573fSAndroid Build Coastguard Worker               setup_method=None, total_bytes=None, full_iteration = 1):
111*1b3f573fSAndroid Build Coastguard Worker    self.full_iteration = full_iteration
112*1b3f573fSAndroid Build Coastguard Worker    self.module = module
113*1b3f573fSAndroid Build Coastguard Worker    self.test_method = test_method
114*1b3f573fSAndroid Build Coastguard Worker    self.setup_method = setup_method
115*1b3f573fSAndroid Build Coastguard Worker    self.total_bytes = total_bytes
116*1b3f573fSAndroid Build Coastguard Worker
117*1b3f573fSAndroid Build Coastguard Worker  def set_test_method(self, test_method):
118*1b3f573fSAndroid Build Coastguard Worker    self.test_method = test_method
119*1b3f573fSAndroid Build Coastguard Worker
120*1b3f573fSAndroid Build Coastguard Worker  def full_setup_code(self, setup_method_args=''):
121*1b3f573fSAndroid Build Coastguard Worker    setup_code = ""
122*1b3f573fSAndroid Build Coastguard Worker    setup_code += "from %s import %s\n" % (self.module, self.test_method)
123*1b3f573fSAndroid Build Coastguard Worker    setup_code += "from %s import %s\n" % (self.module, self.setup_method)
124*1b3f573fSAndroid Build Coastguard Worker    setup_code += "%s(%s)\n" % (self.setup_method, setup_method_args)
125*1b3f573fSAndroid Build Coastguard Worker    return setup_code
126*1b3f573fSAndroid Build Coastguard Worker
127*1b3f573fSAndroid Build Coastguard Worker  def dry_run(self, test_method_args='', setup_method_args=''):
128*1b3f573fSAndroid Build Coastguard Worker    return timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args),
129*1b3f573fSAndroid Build Coastguard Worker                         setup=self.full_setup_code(setup_method_args),
130*1b3f573fSAndroid Build Coastguard Worker                         number=self.full_iteration);
131*1b3f573fSAndroid Build Coastguard Worker
132*1b3f573fSAndroid Build Coastguard Worker  def run_benchmark(self, test_method_args='', setup_method_args=''):
133*1b3f573fSAndroid Build Coastguard Worker    reps = self.full_iteration;
134*1b3f573fSAndroid Build Coastguard Worker    t = self.dry_run(test_method_args, setup_method_args);
135*1b3f573fSAndroid Build Coastguard Worker    if t < 3 :
136*1b3f573fSAndroid Build Coastguard Worker      reps = int(math.ceil(3 / t)) * self.full_iteration
137*1b3f573fSAndroid Build Coastguard Worker    if reps != self.full_iteration:
138*1b3f573fSAndroid Build Coastguard Worker        t = timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args),
139*1b3f573fSAndroid Build Coastguard Worker                          setup=self.full_setup_code(setup_method_args),
140*1b3f573fSAndroid Build Coastguard Worker                          number=reps);
141*1b3f573fSAndroid Build Coastguard Worker    return self.total_bytes * 1.0 / 2 ** 20 / (1.0 * t / reps * self.full_iteration)
142*1b3f573fSAndroid Build Coastguard Worker
143*1b3f573fSAndroid Build Coastguard Worker
144*1b3f573fSAndroid Build Coastguard Workerif __name__ == "__main__":
145*1b3f573fSAndroid Build Coastguard Worker  results = []
146*1b3f573fSAndroid Build Coastguard Worker  for file in args.data_files:
147*1b3f573fSAndroid Build Coastguard Worker    results.append(run_one_test(file))
148*1b3f573fSAndroid Build Coastguard Worker
149*1b3f573fSAndroid Build Coastguard Worker  if args.json != "no":
150*1b3f573fSAndroid Build Coastguard Worker    print(json.dumps(results))
151*1b3f573fSAndroid Build Coastguard Worker  else:
152*1b3f573fSAndroid Build Coastguard Worker    for result in results:
153*1b3f573fSAndroid Build Coastguard Worker      print("Message %s of dataset file %s" % \
154*1b3f573fSAndroid Build Coastguard Worker          (result["message_name"], result["filename"]))
155*1b3f573fSAndroid Build Coastguard Worker      print("Average throughput for parse_from_benchmark: %.2f MB/s" % \
156*1b3f573fSAndroid Build Coastguard Worker          (result["benchmarks"][ \
157*1b3f573fSAndroid Build Coastguard Worker                      args.behavior_prefix + "_parse_from_benchmark"]))
158*1b3f573fSAndroid Build Coastguard Worker      print("Average throughput for serialize_to_benchmark: %.2f MB/s" % \
159*1b3f573fSAndroid Build Coastguard Worker          (result["benchmarks"][ \
160*1b3f573fSAndroid Build Coastguard Worker                      args.behavior_prefix + "_serialize_to_benchmark"]))
161*1b3f573fSAndroid Build Coastguard Worker      print("")
162