aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/benchmark-conf-to-json.py252
1 files changed, 252 insertions, 0 deletions
diff --git a/tools/benchmark-conf-to-json.py b/tools/benchmark-conf-to-json.py
new file mode 100755
index 00000000..928797a1
--- /dev/null
+++ b/tools/benchmark-conf-to-json.py
@@ -0,0 +1,252 @@
+#!/usr/bin/python
+# Script to convert benchmark.conf to benchmark.json
+# Hopefully we won't have to maintain benchmark.conf files any longer after
+# we fully switch to JSON.
+
+from configparser import ConfigParser as config_parser
+from collections import defaultdict
+import json
+import sys
+import re
+
+def guess_old_style_used_threads(bench_name, num_threads):
+ if bench_name == 'CPU Fibonacci':
+ return 1
+ if bench_name == 'CPU FFT':
+ if num_threads >= 4:
+ return 4
+ if num_threads >= 2:
+ return 2
+ return 1
+ if bench_name == 'CPU N-Queens':
+ if num_threads >= 10:
+ return 10
+ if num_threads >= 5:
+ return 5
+ if num_threads >= 2:
+ return 2
+ return 1
+ return num_threads
+
+def first_truthy_or_none(*args):
+ for arg in args:
+ if arg:
+ return arg
+ return None
+
+def nice_cpu_name(name,
+ trademark_stuff = re.compile(r'\((r|tm|c)\)', re.I),
+ vendor_intel = re.compile(r'Intel '),
+ vendor_amd = re.compile(r'AMD '),
+ integrated_processor = re.compile(r'(Integrated Processor|Processor)', re.I),
+ frequency = re.compile(r'(\d+\.?\d+?\+?\s*[GH]z)')):
+ # Cleaned-up port of nice_name_x86_cpuid_model_string() from
+ # deps/sysobj_early/src/nice_name.c
+
+ name = name.strip()
+
+ name = name.replace("@", "")
+ name = trademark_stuff.sub("", name)
+
+ # Move vendor to front
+ match = first_truthy_or_none(vendor_intel.search(name), vendor_amd.search(name))
+ if match:
+ span = match.span()
+ name = name[span[0]:span[1]] + name[0:span[0]] + name[span[1]:]
+
+ # Remove vendor-specific crud
+ if name.startswith("AMD"):
+ name = name.replace("Mobile Technology", "Mobile")
+ name = name.replace("with Radeon", "")
+ name = name.replace("Radeon", "")
+ if "COMPUTE CORES" in name:
+ name, _ = name.split(',', 2)
+ if "X2" in name:
+ name = name.replace("Dual-Core", "")
+ name = name.replace("Dual Core", "")
+ if "X3" in name:
+ name = name.replace("Triple-Core", "")
+ if "X4" in name:
+ name = name.replace("Quad-Core", "")
+ elif name.startswith("Cyrix"):
+ name = name.replace("tm ", "")
+ else:
+ name = name.replace("Genuine Intel", "Intel")
+
+ name = name.replace(" CPU", "")
+ name = name.replace(" APU", "")
+ name = integrated_processor.sub("", name)
+ name = frequency.sub("", name)
+
+ for core_count in ("Dual", "Triple", "Quad", "Six",
+ "Eight", "Octal", "Twelve", "Sixteen",
+ "8", "16", "24", "32", "48", "56", "64"):
+ name = name.replace("%s-Core" % core_count, "")
+ name = name.replace("%s Core" % core_count, "")
+
+ while " " in name:
+ name = name.replace(" ", " ")
+
+ return name.strip()
+
+def cleanup_old_style_cpu_name(name):
+ for n in ('Intel', 'AMD', 'VIA', 'Cyrix'):
+ if n in name:
+ return nice_cpu_name(name)
+ return name
+
+def cpu_config_val(config,
+ mult_freq_re = re.compile(r'((?P<num_cpu>\d+)x\s+)?(?P<freq>\d+\.?\d*)')):
+ # "2x 1400.00 MHz + 2x 800.00 MHz" -> 4400.0
+ value = 0.0
+ for _, num, val in mult_freq_re.findall(config):
+ value += float(val) * (float(num) if num else 1.0)
+ return value
+
+def cpu_config_cmp(config1, config2):
+ r0 = cpu_config_val(config1)
+ r1 = cpu_config_val(config2)
+ if r0 == r1:
+ return 0
+ if r0 < r1:
+ return -1
+ return 1
+
+def cpu_config_is_close(config1, config2):
+ r0 = cpu_config_val(config1)
+ r1 = cpu_config_val(config2)
+ r1n = r1 * 0.9
+ return r0 > r1n and r0 < r1
+
+def guess_old_style_cpu_config(cpu_config, num_logical_cpus,
+ frequency_re = re.compile(r'(?P<freq>\d+\.?\d+)\s*(?P<mult>[GH])z')):
+ freq_mult = frequency_re.match(cpu_config)
+ if not freq_mult:
+ if num_logical_cpus > 1:
+ return '%dx %s' % (num_logical_cpus, cpu_config)
+ return cpu_config
+
+ freq, mult = freq_mult.groups()
+ freq = atof(freq)
+ if mult[0] == 'G':
+ freq *= 1000
+
+ candidate_config = "%dx %.2f MHz" % (num_logical_cpus, freq)
+ if cpu_config_cmp(cpu_config, candidate_config) == -1 and \
+ not cpu_config_is_close(cpu_config, candidate_config):
+ return candidate_config
+
+ return cpu_config
+
+def parse_old_style_cpu_info(cpu_config, cpu_name, bench_name,
+ old_style_cpu_name_re = re.compile('\s*(?P<numcpu>\d+)?(x?\s+)?(?P<cpuname>.*)')):
+ num_cpus = old_style_cpu_name_re.match(cpu_name)
+ assert num_cpus
+
+ groups = num_cpus.groupdict()
+ num_logical_cpus = int(groups['numcpu']) if groups['numcpu'] else 1
+ return {
+ 'NumThreads': num_logical_cpus,
+ 'NumCores': -1,
+ 'NumCpus': -1,
+ 'CpuName': cleanup_old_style_cpu_name(groups['cpuname']),
+ 'CpuConfig': guess_old_style_cpu_config(cpu_config, num_logical_cpus),
+ 'UsedThreads': guess_old_style_used_threads(bench_name, num_logical_cpus),
+ }
+
+def generate_machine_id(bench,
+ invalid_chars_re = re.compile(r'[^A-Za-z0-9\(\);]')):
+ mid = "%s;%s;%.2f" % (
+ bench['Board'] if 'Board' in bench else '(Unknown)',
+ bench['CpuName'],
+ cpu_config_val(bench['CpuConfig']),
+ )
+
+ return invalid_chars_re.sub("_", mid)
+
+def parse_new_style_bench_value(value):
+ values = value.strip().split(';')
+
+ if len(values) >= 3:
+ result = float(values[0].replace(",", "."))
+ elapsed_time = float(values[1].replace(",", "."))
+ threads_used = int(values[2])
+ else:
+ result = 0
+ elapsed_time = 0
+ threads_used = 0
+
+ benchmark_version = int(values[3]) if len(values) >= 4 else 1
+ extra = values[4] if len(values) >= 5 and not '|' in values[4] else ''
+ user_note = values[5] if len(values) >= 6 and not '|' in values[5] else ''
+
+ return {
+ 'BenchmarkResult': result,
+ 'ElapsedTime': elapsed_time,
+ 'UsedThreads': threads_used,
+ 'BenchmarkVersion': benchmark_version,
+ 'ExtraInfo': extra,
+ 'UserNote': user_note,
+ }
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print("Usage: benchmark-conf-to-json.py benchmark.conf")
+ sys.exit(1)
+
+ cfg = config_parser(strict=False)
+ cfg.optionxform = lambda opt: opt
+ cfg.read(sys.argv[1])
+
+ out = defaultdict(lambda: [])
+
+ for section in cfg.sections():
+ if section == 'param':
+ continue
+
+ for key in cfg[section]:
+ values = cfg[section][key].split('|')
+
+ if len(values) >= 10:
+ bench = {
+ 'MachineId': key,
+ 'Board': values[2],
+ 'CpuName': values[3],
+ 'CpuDesc': values[4],
+ 'CpuConfig': values[5].replace(",", "."),
+ 'MemoryInKiB': int(values[6]),
+ 'NumCpus': int(values[7]),
+ 'NumCores': int(values[8]),
+ 'NumThreads': int(values[9]),
+ }
+ bench.update(parse_new_style_bench_value(values[0]))
+ if len(values) >= 11:
+ bench['OpenGlRenderer'] = values[10]
+ if len(values) >= 12:
+ bench['GpuDesc'] = values[11]
+ if len(values) >= 13:
+ bench['MachineDataVersion'] = int(values[12])
+ if len(values) >= 14:
+ bench['PointerBits'] = int(values[13])
+ if len(values) >= 15:
+ bench['DataFromSuperUser'] = int(values[14])
+ if len(values) >= 16:
+ bench['PhysicalMemoryInMiB'] = int(values[15])
+ if len(values) >= 17:
+ bench['MemoryTypes'] = values[16]
+ elif len(values) >= 2:
+ bench = {
+ 'BenchmarkResult': float(values[0]),
+ }
+
+ bench.update(parse_old_style_cpu_info(
+ values[1].replace(",", "."),
+ key,
+ section))
+ bench['MachineId'] = generate_machine_id(bench)
+ else:
+ raise SyntaxError("unexpected value length: %d (%s)" % (len(values), values))
+
+ out[section].append(bench)
+
+ print(json.dumps(out))