result_parser.py 8.47 KB
Newer Older
1 2
# This import depends on the automake rule protoc_middleman, please make sure
# protoc_middleman has been built before run this file.
3 4 5 6 7
import json
import re
import os.path
# BEGIN OPENSOURCE
import sys
8
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
9
# END OPENSOURCE
10 11
import tmp.benchmarks_pb2 as benchmarks_pb2

12
__file_size_map = {}
13

14 15 16 17 18
def __get_data_size(filename):
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + "/../" + filename
  if filename in __file_size_map:
    return __file_size_map[filename]
19 20
  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
  benchmark_dataset.ParseFromString(
21
      open(filename).read())
22 23 24 25 26
  size = 0
  count = 0
  for payload in benchmark_dataset.payload:
    size += len(payload)
    count += 1
27
  __file_size_map[filename] = (size, 1.0 * size / count)
28 29 30
  return size, 1.0 * size / count


31
def __extract_file_name(file_name):
32 33 34 35 36 37 38 39
  name_list = re.split("[/\.]", file_name)
  short_file_name = ""
  for name in name_list:
    if name[:14] == "google_message":
      short_file_name = name
  return short_file_name


40
__results = []
41 42 43


# CPP results example:
44 45
# [
#   "benchmarks": [
46 47
#     {
#       "bytes_per_second": int,
48 49
#       "cpu_time_ns": double,
#       "iterations": int,
50
#       "name: string,
51
#       "real_time_ns: double,
52 53
#       ...
#     },
54
#     ...
55
#   ],
56
#   ...
57
# ]
58
def __parse_cpp_result(filename):
59 60 61 62 63 64 65 66 67 68
  if filename == "":
    return
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
  with open(filename) as f:
    results = json.loads(f.read())
    for benchmark in results["benchmarks"]:
      data_filename = "".join(
          re.split("(_parse_|_serialize)", benchmark["name"])[0])
      behavior = benchmark["name"][len(data_filename) + 1:]
69 70 71
      if data_filename[:2] == "BM":
        data_filename = data_filename[3:]
      __results.append({
72
        "language": "cpp",
73
        "dataFilename": data_filename,
74 75 76 77 78
        "behavior": behavior,
        "throughput": benchmark["bytes_per_second"] / 2.0 ** 20
      })


79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
# Synthetic benchmark results example:
# [
#   "benchmarks": [
#     {
#       "cpu_time_ns": double,
#       "iterations": int,
#       "name: string,
#       "real_time_ns: double,
#       ...
#     },
#     ...
#   ],
#   ...
# ]
def __parse_synthetic_result(filename):
  if filename == "":
    return
  if filename[0] != "/":
    filename = os.path.dirname(os.path.abspath(__file__)) + "/" + filename
  with open(filename) as f:
    results = json.loads(f.read())
    for benchmark in results["benchmarks"]:
      __results.append({
          "language": "cpp",
          "dataFilename": "",
          "behavior": "synthetic",
          "throughput": 10.0**9 / benchmark["cpu_time_ns"]
      })


109
# Python results example:
110 111
# [
#   [
112 113 114
#     {
#       "filename": string,
#       "benchmarks": {
115
#         behavior: results,
116 117 118
#         ...
#       },
#     },
119
#     ...
120
#   ], #pure-python
121
#   ...
122
# ]
123
def __parse_python_result(filename):
124 125 126 127 128 129 130 131
  if filename == "":
    return
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
  with open(filename) as f:
    results_list = json.loads(f.read())
    for results in results_list:
      for result in results:
132
        _, avg_size = __get_data_size(result["filename"])
133
        for behavior in result["benchmarks"]:
134
          __results.append({
135
            "language": "python",
136
            "dataFilename": __extract_file_name(result["filename"]),
137
            "behavior": behavior,
138
            "throughput": result["benchmarks"][behavior]
139 140 141 142
          })


# Java results example:
143
# [
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
#   {
#     "id": string,
#     "instrumentSpec": {...},
#     "measurements": [
#       {
#         "weight": float,
#         "value": {
#           "magnitude": float,
#           "unit": string
#         },
#         ...
#       },
#       ...
#     ],
#     "run": {...},
#     "scenario": {
#       "benchmarkSpec": {
#         "methodName": string,
#         "parameters": {
#            defined parameters in the benchmark: parameters value
#         },
#         ...
#       },
#       ...
#     }
169 170 171
#
#   },
#   ...
172
# ]
173
def __parse_java_result(filename):
174 175 176 177 178 179 180 181 182 183 184 185 186
  if filename == "":
    return
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
  with open(filename) as f:
    results = json.loads(f.read())
    for result in results:
      total_weight = 0
      total_value = 0
      for measurement in result["measurements"]:
        total_weight += measurement["weight"]
        total_value += measurement["value"]["magnitude"]
      avg_time = total_value * 1.0 / total_weight
187
      total_size, _ = __get_data_size(
188
          result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"])
189
      __results.append({
190 191 192
        "language": "java",
        "throughput": total_size / avg_time * 1e9 / 2 ** 20,
        "behavior": result["scenario"]["benchmarkSpec"]["methodName"],
193
        "dataFilename": __extract_file_name(
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
            result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"])
      })


# Go benchmark results:
#
# goos: linux
# goarch: amd64
# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Unmarshal-12               3000      705784 ns/op
# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Marshal-12                 2000      634648 ns/op
# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Size-12                    5000      244174 ns/op
# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Clone-12                    300     4120954 ns/op
# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Merge-12                    300     4108632 ns/op
# PASS
# ok    _/usr/local/google/home/yilunchong/mygit/protobuf/benchmarks  124.173s
209
def __parse_go_result(filename):
210 211 212 213 214 215 216 217 218 219 220
  if filename == "":
    return
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
  with open(filename) as f:
    for line in f:
      result_list = re.split("[\ \t]+", line)
      if result_list[0][:9] != "Benchmark":
        continue
      first_slash_index = result_list[0].find('/')
      last_slash_index = result_list[0].rfind('/')
221
      full_filename = result_list[0][first_slash_index+1:last_slash_index]
222
      total_bytes, _ = __get_data_size(full_filename)
223 224 225 226 227 228
      behavior_with_suffix = result_list[0][last_slash_index+1:]
      last_dash = behavior_with_suffix.rfind("-")
      if last_dash == -1:
        behavior = behavior_with_suffix
      else:
        behavior = behavior_with_suffix[:last_dash]
229 230
      __results.append({
        "dataFilename": __extract_file_name(full_filename),
231 232 233 234 235
        "throughput": total_bytes / float(result_list[2]) * 1e9 / 2 ** 20,
        "behavior": behavior,
        "language": "go"
      })

236

Yilun Chong's avatar
Yilun Chong committed
237
# Self built json results example:
238 239 240 241 242 243 244 245 246 247 248
#
# [
#   {
#     "filename": string,
#     "benchmarks": {
#       behavior: results,
#       ...
#     },
#   },
#   ...
# ]
Yilun Chong's avatar
Yilun Chong committed
249
def __parse_custom_result(filename, language):
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
  if filename == "":
    return
  if filename[0] != '/':
    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
  with open(filename) as f:
    results = json.loads(f.read())
    for result in results:
      _, avg_size = __get_data_size(result["filename"])
      for behavior in result["benchmarks"]:
        __results.append({
          "language": language,
          "dataFilename": __extract_file_name(result["filename"]),
          "behavior": behavior,
          "throughput": result["benchmarks"][behavior]
        })


Yilun Chong's avatar
Yilun Chong committed
267
def __parse_js_result(filename, language):
Yilun Chong's avatar
Yilun Chong committed
268
  return __parse_custom_result(filename, language)
Yilun Chong's avatar
Yilun Chong committed
269 270

def __parse_php_result(filename, language):
Yilun Chong's avatar
Yilun Chong committed
271
  return __parse_custom_result(filename, language)
Yilun Chong's avatar
Yilun Chong committed
272

273

274 275 276 277
def get_result_from_file(cpp_file="",
                         java_file="",
                         python_file="",
                         go_file="",
278 279 280 281
                         synthetic_file="",
                         node_file="",
                         php_c_file="",
                         php_file=""):
282 283 284 285 286 287 288 289 290
  results = {}
  if cpp_file != "":
    __parse_cpp_result(cpp_file)
  if java_file != "":
    __parse_java_result(java_file)
  if python_file != "":
    __parse_python_result(python_file)
  if go_file != "":
    __parse_go_result(go_file)
291 292
  if synthetic_file != "":
    __parse_synthetic_result(synthetic_file)
293
  if node_file != "":
Yilun Chong's avatar
Yilun Chong committed
294
    __parse_js_result(node_file, "node")
295
  if php_file != "":
Yilun Chong's avatar
Yilun Chong committed
296
    __parse_php_result(php_file, "php")
297
  if php_c_file != "":
Yilun Chong's avatar
Yilun Chong committed
298
    __parse_php_result(php_c_file, "php")        
299

300
  return __results