aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/codegen/core/gen_stats_data.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/codegen/core/gen_stats_data.py')
-rwxr-xr-xtools/codegen/core/gen_stats_data.py705
1 files changed, 372 insertions, 333 deletions
diff --git a/tools/codegen/core/gen_stats_data.py b/tools/codegen/core/gen_stats_data.py
index d439d99a8c..4fd9fa437e 100755
--- a/tools/codegen/core/gen_stats_data.py
+++ b/tools/codegen/core/gen_stats_data.py
@@ -22,397 +22,436 @@ import yaml
import json
with open('src/core/lib/debug/stats_data.yaml') as f:
- attrs = yaml.load(f.read())
+ attrs = yaml.load(f.read())
REQUIRED_FIELDS = ['name', 'doc']
+
def make_type(name, fields):
- return (collections.namedtuple(name, ' '.join(list(set(REQUIRED_FIELDS + fields)))), [])
+ return (collections.namedtuple(
+ name, ' '.join(list(set(REQUIRED_FIELDS + fields)))), [])
+
def c_str(s, encoding='ascii'):
- if isinstance(s, unicode):
- s = s.encode(encoding)
- result = ''
- for c in s:
- if not (32 <= ord(c) < 127) or c in ('\\', '"'):
- result += '\\%03o' % ord(c)
- else:
- result += c
- return '"' + result + '"'
-
-types = (
- make_type('Counter', []),
- make_type('Histogram', ['max', 'buckets']),
-)
+ if isinstance(s, unicode):
+ s = s.encode(encoding)
+ result = ''
+ for c in s:
+ if not (32 <= ord(c) < 127) or c in ('\\', '"'):
+ result += '\\%03o' % ord(c)
+ else:
+ result += c
+ return '"' + result + '"'
+
+
+types = (make_type('Counter', []), make_type('Histogram', ['max', 'buckets']),)
inst_map = dict((t[0].__name__, t[1]) for t in types)
stats = []
for attr in attrs:
- found = False
- for t, lst in types:
- t_name = t.__name__.lower()
- if t_name in attr:
- name = attr[t_name]
- del attr[t_name]
- lst.append(t(name=name, **attr))
- found = True
- break
- assert found, "Bad decl: %s" % attr
+ found = False
+ for t, lst in types:
+ t_name = t.__name__.lower()
+ if t_name in attr:
+ name = attr[t_name]
+ del attr[t_name]
+ lst.append(t(name=name, **attr))
+ found = True
+ break
+ assert found, "Bad decl: %s" % attr
+
def dbl2u64(d):
- return ctypes.c_ulonglong.from_buffer(ctypes.c_double(d)).value
+ return ctypes.c_ulonglong.from_buffer(ctypes.c_double(d)).value
+
def shift_works_until(mapped_bounds, shift_bits):
- for i, ab in enumerate(zip(mapped_bounds, mapped_bounds[1:])):
- a, b = ab
- if (a >> shift_bits) == (b >> shift_bits):
- return i
- return len(mapped_bounds)
+ for i, ab in enumerate(zip(mapped_bounds, mapped_bounds[1:])):
+ a, b = ab
+ if (a >> shift_bits) == (b >> shift_bits):
+ return i
+ return len(mapped_bounds)
+
def find_ideal_shift(mapped_bounds, max_size):
- best = None
- for shift_bits in reversed(range(0,64)):
- n = shift_works_until(mapped_bounds, shift_bits)
- if n == 0: continue
- table_size = mapped_bounds[n-1] >> shift_bits
- if table_size > max_size: continue
- if table_size > 65535: continue
- if best is None:
- best = (shift_bits, n, table_size)
- elif best[1] < n:
- best = (shift_bits, n, table_size)
- print best
- return best
+ best = None
+ for shift_bits in reversed(range(0, 64)):
+ n = shift_works_until(mapped_bounds, shift_bits)
+ if n == 0: continue
+ table_size = mapped_bounds[n - 1] >> shift_bits
+ if table_size > max_size: continue
+ if table_size > 65535: continue
+ if best is None:
+ best = (shift_bits, n, table_size)
+ elif best[1] < n:
+ best = (shift_bits, n, table_size)
+ print best
+ return best
+
def gen_map_table(mapped_bounds, shift_data):
- tbl = []
- cur = 0
- print mapped_bounds
- mapped_bounds = [x >> shift_data[0] for x in mapped_bounds]
- print mapped_bounds
- for i in range(0, mapped_bounds[shift_data[1]-1]):
- while i > mapped_bounds[cur]:
- cur += 1
- tbl.append(cur)
- return tbl
+ tbl = []
+ cur = 0
+ print mapped_bounds
+ mapped_bounds = [x >> shift_data[0] for x in mapped_bounds]
+ print mapped_bounds
+ for i in range(0, mapped_bounds[shift_data[1] - 1]):
+ while i > mapped_bounds[cur]:
+ cur += 1
+ tbl.append(cur)
+ return tbl
+
static_tables = []
+
def decl_static_table(values, type):
- global static_tables
- v = (type, values)
- for i, vp in enumerate(static_tables):
- if v == vp: return i
- print "ADD TABLE: %s %r" % (type, values)
- r = len(static_tables)
- static_tables.append(v)
- return r
+ global static_tables
+ v = (type, values)
+ for i, vp in enumerate(static_tables):
+ if v == vp: return i
+ print "ADD TABLE: %s %r" % (type, values)
+ r = len(static_tables)
+ static_tables.append(v)
+ return r
+
def type_for_uint_table(table):
- mv = max(table)
- if mv < 2**8:
- return 'uint8_t'
- elif mv < 2**16:
- return 'uint16_t'
- elif mv < 2**32:
- return 'uint32_t'
- else:
- return 'uint64_t'
+ mv = max(table)
+ if mv < 2**8:
+ return 'uint8_t'
+ elif mv < 2**16:
+ return 'uint16_t'
+ elif mv < 2**32:
+ return 'uint32_t'
+ else:
+ return 'uint64_t'
+
def gen_bucket_code(histogram):
- bounds = [0, 1]
- done_trivial = False
- done_unmapped = False
- first_nontrivial = None
- first_unmapped = None
- while len(bounds) < histogram.buckets + 1:
- if len(bounds) == histogram.buckets:
- nextb = int(histogram.max)
+ bounds = [0, 1]
+ done_trivial = False
+ done_unmapped = False
+ first_nontrivial = None
+ first_unmapped = None
+ while len(bounds) < histogram.buckets + 1:
+ if len(bounds) == histogram.buckets:
+ nextb = int(histogram.max)
+ else:
+ mul = math.pow(
+ float(histogram.max) / bounds[-1],
+ 1.0 / (histogram.buckets + 1 - len(bounds)))
+ nextb = int(math.ceil(bounds[-1] * mul))
+ if nextb <= bounds[-1] + 1:
+ nextb = bounds[-1] + 1
+ elif not done_trivial:
+ done_trivial = True
+ first_nontrivial = len(bounds)
+ bounds.append(nextb)
+ bounds_idx = decl_static_table(bounds, 'int')
+ if done_trivial:
+ first_nontrivial_code = dbl2u64(first_nontrivial)
+ code_bounds = [dbl2u64(x) - first_nontrivial_code for x in bounds]
+ shift_data = find_ideal_shift(code_bounds[first_nontrivial:], 256 *
+ histogram.buckets)
+ #print first_nontrivial, shift_data, bounds
+ #if shift_data is not None: print [hex(x >> shift_data[0]) for x in code_bounds[first_nontrivial:]]
+ code = 'value = GPR_CLAMP(value, 0, %d);\n' % histogram.max
+ map_table = gen_map_table(code_bounds[first_nontrivial:], shift_data)
+ if first_nontrivial is None:
+ code += ('GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, value);\n' %
+ histogram.name.upper())
else:
- mul = math.pow(float(histogram.max) / bounds[-1],
- 1.0 / (histogram.buckets + 1 - len(bounds)))
- nextb = int(math.ceil(bounds[-1] * mul))
- if nextb <= bounds[-1] + 1:
- nextb = bounds[-1] + 1
- elif not done_trivial:
- done_trivial = True
- first_nontrivial = len(bounds)
- bounds.append(nextb)
- bounds_idx = decl_static_table(bounds, 'int')
- if done_trivial:
- first_nontrivial_code = dbl2u64(first_nontrivial)
- code_bounds = [dbl2u64(x) - first_nontrivial_code for x in bounds]
- shift_data = find_ideal_shift(code_bounds[first_nontrivial:], 256 * histogram.buckets)
- #print first_nontrivial, shift_data, bounds
- #if shift_data is not None: print [hex(x >> shift_data[0]) for x in code_bounds[first_nontrivial:]]
- code = 'value = GPR_CLAMP(value, 0, %d);\n' % histogram.max
- map_table = gen_map_table(code_bounds[first_nontrivial:], shift_data)
- if first_nontrivial is None:
- code += ('GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, value);\n'
- % histogram.name.upper())
- else:
- code += 'if (value < %d) {\n' % first_nontrivial
- code += ('GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, value);\n'
- % histogram.name.upper())
- code += 'return;\n'
- code += '}'
- first_nontrivial_code = dbl2u64(first_nontrivial)
- if shift_data is not None:
- map_table_idx = decl_static_table(map_table, type_for_uint_table(map_table))
- code += 'union { double dbl; uint64_t uint; } _val, _bkt;\n'
- code += '_val.dbl = value;\n'
- code += 'if (_val.uint < %dull) {\n' % ((map_table[-1] << shift_data[0]) + first_nontrivial_code)
- code += 'int bucket = '
- code += 'grpc_stats_table_%d[((_val.uint - %dull) >> %d)] + %d;\n' % (map_table_idx, first_nontrivial_code, shift_data[0], first_nontrivial)
- code += '_bkt.dbl = grpc_stats_table_%d[bucket];\n' % bounds_idx
- code += 'bucket -= (_val.uint < _bkt.uint);\n'
- code += 'GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, bucket);\n' % histogram.name.upper()
- code += 'return;\n'
- code += '}\n'
- code += 'GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, '% histogram.name.upper()
- code += 'grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_%d, %d));\n' % (bounds_idx, histogram.buckets)
- return (code, bounds_idx)
+ code += 'if (value < %d) {\n' % first_nontrivial
+ code += ('GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, value);\n' %
+ histogram.name.upper())
+ code += 'return;\n'
+ code += '}'
+ first_nontrivial_code = dbl2u64(first_nontrivial)
+ if shift_data is not None:
+ map_table_idx = decl_static_table(map_table,
+ type_for_uint_table(map_table))
+ code += 'union { double dbl; uint64_t uint; } _val, _bkt;\n'
+ code += '_val.dbl = value;\n'
+ code += 'if (_val.uint < %dull) {\n' % (
+ (map_table[-1] << shift_data[0]) + first_nontrivial_code)
+ code += 'int bucket = '
+ code += 'grpc_stats_table_%d[((_val.uint - %dull) >> %d)] + %d;\n' % (
+ map_table_idx, first_nontrivial_code, shift_data[0],
+ first_nontrivial)
+ code += '_bkt.dbl = grpc_stats_table_%d[bucket];\n' % bounds_idx
+ code += 'bucket -= (_val.uint < _bkt.uint);\n'
+ code += 'GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, bucket);\n' % histogram.name.upper(
+ )
+ code += 'return;\n'
+ code += '}\n'
+ code += 'GRPC_STATS_INC_HISTOGRAM(GRPC_STATS_HISTOGRAM_%s, ' % histogram.name.upper(
+ )
+ code += 'grpc_stats_histo_find_bucket_slow(value, grpc_stats_table_%d, %d));\n' % (
+ bounds_idx, histogram.buckets)
+ return (code, bounds_idx)
+
# utility: print a big comment block into a set of files
def put_banner(files, banner):
- for f in files:
- print >>f, '/*'
- for line in banner:
- print >>f, ' * %s' % line
- print >>f, ' */'
- print >>f
+ for f in files:
+ print >> f, '/*'
+ for line in banner:
+ print >> f, ' * %s' % line
+ print >> f, ' */'
+ print >> f
+
with open('src/core/lib/debug/stats_data.h', 'w') as H:
- # copy-paste copyright notice from this file
- with open(sys.argv[0]) as my_source:
- copyright = []
- for line in my_source:
- if line[0] != '#': break
- for line in my_source:
- if line[0] == '#':
- copyright.append(line)
- break
- for line in my_source:
- if line[0] != '#':
- break
- copyright.append(line)
- put_banner([H], [line[2:].rstrip() for line in copyright])
-
- put_banner([H], ["Automatically generated by tools/codegen/core/gen_stats_data.py"])
-
- print >>H, "#ifndef GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
- print >>H, "#define GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
- print >>H
- print >>H, "#include <inttypes.h>"
- print >>H, "#include \"src/core/lib/iomgr/exec_ctx.h\""
- print >>H
- print >>H, "#ifdef __cplusplus"
- print >>H, "extern \"C\" {"
- print >>H, "#endif"
- print >>H
-
- for typename, instances in sorted(inst_map.items()):
- print >>H, "typedef enum {"
- for inst in instances:
- print >>H, " GRPC_STATS_%s_%s," % (typename.upper(), inst.name.upper())
- print >>H, " GRPC_STATS_%s_COUNT" % (typename.upper())
- print >>H, "} grpc_stats_%ss;" % (typename.lower())
- print >>H, "extern const char *grpc_stats_%s_name[GRPC_STATS_%s_COUNT];" % (
- typename.lower(), typename.upper())
- print >>H, "extern const char *grpc_stats_%s_doc[GRPC_STATS_%s_COUNT];" % (
- typename.lower(), typename.upper())
-
- histo_start = []
- histo_buckets = []
- histo_bucket_boundaries = []
-
- print >>H, "typedef enum {"
- first_slot = 0
- for histogram in inst_map['Histogram']:
- histo_start.append(first_slot)
- histo_buckets.append(histogram.buckets)
- print >>H, " GRPC_STATS_HISTOGRAM_%s_FIRST_SLOT = %d," % (histogram.name.upper(), first_slot)
- print >>H, " GRPC_STATS_HISTOGRAM_%s_BUCKETS = %d," % (histogram.name.upper(), histogram.buckets)
- first_slot += histogram.buckets
- print >>H, " GRPC_STATS_HISTOGRAM_BUCKETS = %d" % first_slot
- print >>H, "} grpc_stats_histogram_constants;"
-
- for ctr in inst_map['Counter']:
- print >>H, ("#define GRPC_STATS_INC_%s() " +
- "GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_%s)") % (
- ctr.name.upper(), ctr.name.upper())
- for histogram in inst_map['Histogram']:
- print >>H, "#define GRPC_STATS_INC_%s(value) grpc_stats_inc_%s( (int)(value))" % (
- histogram.name.upper(), histogram.name.lower())
- print >>H, "void grpc_stats_inc_%s(int x);" % histogram.name.lower()
-
- for i, tbl in enumerate(static_tables):
- print >>H, "extern const %s grpc_stats_table_%d[%d];" % (tbl[0], i, len(tbl[1]))
-
- print >>H, "extern const int grpc_stats_histo_buckets[%d];" % len(inst_map['Histogram'])
- print >>H, "extern const int grpc_stats_histo_start[%d];" % len(inst_map['Histogram'])
- print >>H, "extern const int *const grpc_stats_histo_bucket_boundaries[%d];" % len(inst_map['Histogram'])
- print >>H, "extern void (*const grpc_stats_inc_histogram[%d])(int x);" % len(inst_map['Histogram'])
-
- print >>H
- print >>H, "#ifdef __cplusplus"
- print >>H, "}"
- print >>H, "#endif"
- print >>H
- print >>H, "#endif /* GRPC_CORE_LIB_DEBUG_STATS_DATA_H */"
+ # copy-paste copyright notice from this file
+ with open(sys.argv[0]) as my_source:
+ copyright = []
+ for line in my_source:
+ if line[0] != '#': break
+ for line in my_source:
+ if line[0] == '#':
+ copyright.append(line)
+ break
+ for line in my_source:
+ if line[0] != '#':
+ break
+ copyright.append(line)
+ put_banner([H], [line[2:].rstrip() for line in copyright])
+
+ put_banner(
+ [H],
+ ["Automatically generated by tools/codegen/core/gen_stats_data.py"])
+
+ print >> H, "#ifndef GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
+ print >> H, "#define GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
+ print >> H
+ print >> H, "#include <inttypes.h>"
+ print >> H, "#include \"src/core/lib/iomgr/exec_ctx.h\""
+ print >> H
+ print >> H, "#ifdef __cplusplus"
+ print >> H, "extern \"C\" {"
+ print >> H, "#endif"
+ print >> H
+
+ for typename, instances in sorted(inst_map.items()):
+ print >> H, "typedef enum {"
+ for inst in instances:
+ print >> H, " GRPC_STATS_%s_%s," % (typename.upper(),
+ inst.name.upper())
+ print >> H, " GRPC_STATS_%s_COUNT" % (typename.upper())
+ print >> H, "} grpc_stats_%ss;" % (typename.lower())
+ print >> H, "extern const char *grpc_stats_%s_name[GRPC_STATS_%s_COUNT];" % (
+ typename.lower(), typename.upper())
+ print >> H, "extern const char *grpc_stats_%s_doc[GRPC_STATS_%s_COUNT];" % (
+ typename.lower(), typename.upper())
+
+ histo_start = []
+ histo_buckets = []
+ histo_bucket_boundaries = []
+
+ print >> H, "typedef enum {"
+ first_slot = 0
+ for histogram in inst_map['Histogram']:
+ histo_start.append(first_slot)
+ histo_buckets.append(histogram.buckets)
+ print >> H, " GRPC_STATS_HISTOGRAM_%s_FIRST_SLOT = %d," % (
+ histogram.name.upper(), first_slot)
+ print >> H, " GRPC_STATS_HISTOGRAM_%s_BUCKETS = %d," % (
+ histogram.name.upper(), histogram.buckets)
+ first_slot += histogram.buckets
+ print >> H, " GRPC_STATS_HISTOGRAM_BUCKETS = %d" % first_slot
+ print >> H, "} grpc_stats_histogram_constants;"
+
+ for ctr in inst_map['Counter']:
+ print >> H, ("#define GRPC_STATS_INC_%s() " +
+ "GRPC_STATS_INC_COUNTER(GRPC_STATS_COUNTER_%s)") % (
+ ctr.name.upper(), ctr.name.upper())
+ for histogram in inst_map['Histogram']:
+ print >> H, "#define GRPC_STATS_INC_%s(value) grpc_stats_inc_%s( (int)(value))" % (
+ histogram.name.upper(), histogram.name.lower())
+ print >> H, "void grpc_stats_inc_%s(int x);" % histogram.name.lower()
+
+ for i, tbl in enumerate(static_tables):
+ print >> H, "extern const %s grpc_stats_table_%d[%d];" % (tbl[0], i,
+ len(tbl[1]))
+
+ print >> H, "extern const int grpc_stats_histo_buckets[%d];" % len(
+ inst_map['Histogram'])
+ print >> H, "extern const int grpc_stats_histo_start[%d];" % len(
+ inst_map['Histogram'])
+ print >> H, "extern const int *const grpc_stats_histo_bucket_boundaries[%d];" % len(
+ inst_map['Histogram'])
+ print >> H, "extern void (*const grpc_stats_inc_histogram[%d])(int x);" % len(
+ inst_map['Histogram'])
+
+ print >> H
+ print >> H, "#ifdef __cplusplus"
+ print >> H, "}"
+ print >> H, "#endif"
+ print >> H
+ print >> H, "#endif /* GRPC_CORE_LIB_DEBUG_STATS_DATA_H */"
with open('src/core/lib/debug/stats_data.cc', 'w') as C:
- # copy-paste copyright notice from this file
- with open(sys.argv[0]) as my_source:
- copyright = []
- for line in my_source:
- if line[0] != '#': break
- for line in my_source:
- if line[0] == '#':
- copyright.append(line)
- break
- for line in my_source:
- if line[0] != '#':
- break
- copyright.append(line)
- put_banner([C], [line[2:].rstrip() for line in copyright])
-
- put_banner([C], ["Automatically generated by tools/codegen/core/gen_stats_data.py"])
-
- print >>C, "#include \"src/core/lib/debug/stats_data.h\""
- print >>C, "#include \"src/core/lib/debug/stats.h\""
- print >>C, "#include \"src/core/lib/iomgr/exec_ctx.h\""
- print >>C, "#include <grpc/support/useful.h>"
-
- histo_code = []
- for histogram in inst_map['Histogram']:
- code, bounds_idx = gen_bucket_code(histogram)
- histo_bucket_boundaries.append(bounds_idx)
- histo_code.append(code)
-
- for typename, instances in sorted(inst_map.items()):
- print >>C, "const char *grpc_stats_%s_name[GRPC_STATS_%s_COUNT] = {" % (
- typename.lower(), typename.upper())
- for inst in instances:
- print >>C, " %s," % c_str(inst.name)
- print >>C, "};"
- print >>C, "const char *grpc_stats_%s_doc[GRPC_STATS_%s_COUNT] = {" % (
- typename.lower(), typename.upper())
- for inst in instances:
- print >>C, " %s," % c_str(inst.doc)
- print >>C, "};"
-
- for i, tbl in enumerate(static_tables):
- print >>C, "const %s grpc_stats_table_%d[%d] = {%s};" % (
- tbl[0], i, len(tbl[1]), ','.join('%s' % x for x in tbl[1]))
-
- for histogram, code in zip(inst_map['Histogram'], histo_code):
- print >>C, ("void grpc_stats_inc_%s(int value) {%s}") % (
- histogram.name.lower(),
- code)
-
- print >>C, "const int grpc_stats_histo_buckets[%d] = {%s};" % (
- len(inst_map['Histogram']), ','.join('%s' % x for x in histo_buckets))
- print >>C, "const int grpc_stats_histo_start[%d] = {%s};" % (
- len(inst_map['Histogram']), ','.join('%s' % x for x in histo_start))
- print >>C, "const int *const grpc_stats_histo_bucket_boundaries[%d] = {%s};" % (
- len(inst_map['Histogram']), ','.join('grpc_stats_table_%d' % x for x in histo_bucket_boundaries))
- print >>C, "void (*const grpc_stats_inc_histogram[%d])(int x) = {%s};" % (
- len(inst_map['Histogram']), ','.join('grpc_stats_inc_%s' % histogram.name.lower() for histogram in inst_map['Histogram']))
+ # copy-paste copyright notice from this file
+ with open(sys.argv[0]) as my_source:
+ copyright = []
+ for line in my_source:
+ if line[0] != '#': break
+ for line in my_source:
+ if line[0] == '#':
+ copyright.append(line)
+ break
+ for line in my_source:
+ if line[0] != '#':
+ break
+ copyright.append(line)
+ put_banner([C], [line[2:].rstrip() for line in copyright])
+
+ put_banner(
+ [C],
+ ["Automatically generated by tools/codegen/core/gen_stats_data.py"])
+
+ print >> C, "#include \"src/core/lib/debug/stats_data.h\""
+ print >> C, "#include \"src/core/lib/debug/stats.h\""
+ print >> C, "#include \"src/core/lib/iomgr/exec_ctx.h\""
+ print >> C, "#include <grpc/support/useful.h>"
+
+ histo_code = []
+ for histogram in inst_map['Histogram']:
+ code, bounds_idx = gen_bucket_code(histogram)
+ histo_bucket_boundaries.append(bounds_idx)
+ histo_code.append(code)
+
+ for typename, instances in sorted(inst_map.items()):
+ print >> C, "const char *grpc_stats_%s_name[GRPC_STATS_%s_COUNT] = {" % (
+ typename.lower(), typename.upper())
+ for inst in instances:
+ print >> C, " %s," % c_str(inst.name)
+ print >> C, "};"
+ print >> C, "const char *grpc_stats_%s_doc[GRPC_STATS_%s_COUNT] = {" % (
+ typename.lower(), typename.upper())
+ for inst in instances:
+ print >> C, " %s," % c_str(inst.doc)
+ print >> C, "};"
+
+ for i, tbl in enumerate(static_tables):
+ print >> C, "const %s grpc_stats_table_%d[%d] = {%s};" % (
+ tbl[0], i, len(tbl[1]), ','.join('%s' % x for x in tbl[1]))
+
+ for histogram, code in zip(inst_map['Histogram'], histo_code):
+ print >> C, ("void grpc_stats_inc_%s(int value) {%s}") % (
+ histogram.name.lower(), code)
+
+ print >> C, "const int grpc_stats_histo_buckets[%d] = {%s};" % (
+ len(inst_map['Histogram']), ','.join('%s' % x for x in histo_buckets))
+ print >> C, "const int grpc_stats_histo_start[%d] = {%s};" % (
+ len(inst_map['Histogram']), ','.join('%s' % x for x in histo_start))
+ print >> C, "const int *const grpc_stats_histo_bucket_boundaries[%d] = {%s};" % (
+ len(inst_map['Histogram']), ','.join('grpc_stats_table_%d' % x
+ for x in histo_bucket_boundaries))
+ print >> C, "void (*const grpc_stats_inc_histogram[%d])(int x) = {%s};" % (
+ len(inst_map['Histogram']),
+ ','.join('grpc_stats_inc_%s' % histogram.name.lower()
+ for histogram in inst_map['Histogram']))
# patch qps_test bigquery schema
RECORD_EXPLICIT_PERCENTILES = [50, 95, 99]
with open('tools/run_tests/performance/scenario_result_schema.json', 'r') as f:
- qps_schema = json.loads(f.read())
+ qps_schema = json.loads(f.read())
+
def FindNamed(js, name):
- for el in js:
- if el['name'] == name:
- return el
+ for el in js:
+ if el['name'] == name:
+ return el
+
def RemoveCoreFields(js):
- new_fields = []
- for field in js['fields']:
- if not field['name'].startswith('core_'):
- new_fields.append(field)
- js['fields'] = new_fields
+ new_fields = []
+ for field in js['fields']:
+ if not field['name'].startswith('core_'):
+ new_fields.append(field)
+ js['fields'] = new_fields
+
RemoveCoreFields(FindNamed(qps_schema, 'clientStats'))
RemoveCoreFields(FindNamed(qps_schema, 'serverStats'))
+
def AddCoreFields(js):
- for counter in inst_map['Counter']:
- js['fields'].append({
- 'name': 'core_%s' % counter.name,
- 'type': 'INTEGER',
- 'mode': 'NULLABLE'
- })
- for histogram in inst_map['Histogram']:
- js['fields'].append({
- 'name': 'core_%s' % histogram.name,
- 'type': 'STRING',
- 'mode': 'NULLABLE'
- })
- js['fields'].append({
- 'name': 'core_%s_bkts' % histogram.name,
- 'type': 'STRING',
- 'mode': 'NULLABLE'
- })
- for pctl in RECORD_EXPLICIT_PERCENTILES:
- js['fields'].append({
- 'name': 'core_%s_%dp' % (histogram.name, pctl),
- 'type': 'FLOAT',
- 'mode': 'NULLABLE'
- })
+ for counter in inst_map['Counter']:
+ js['fields'].append({
+ 'name': 'core_%s' % counter.name,
+ 'type': 'INTEGER',
+ 'mode': 'NULLABLE'
+ })
+ for histogram in inst_map['Histogram']:
+ js['fields'].append({
+ 'name': 'core_%s' % histogram.name,
+ 'type': 'STRING',
+ 'mode': 'NULLABLE'
+ })
+ js['fields'].append({
+ 'name': 'core_%s_bkts' % histogram.name,
+ 'type': 'STRING',
+ 'mode': 'NULLABLE'
+ })
+ for pctl in RECORD_EXPLICIT_PERCENTILES:
+ js['fields'].append({
+ 'name': 'core_%s_%dp' % (histogram.name, pctl),
+ 'type': 'FLOAT',
+ 'mode': 'NULLABLE'
+ })
+
AddCoreFields(FindNamed(qps_schema, 'clientStats'))
AddCoreFields(FindNamed(qps_schema, 'serverStats'))
with open('tools/run_tests/performance/scenario_result_schema.json', 'w') as f:
- f.write(json.dumps(qps_schema, indent=2, sort_keys=True))
+ f.write(json.dumps(qps_schema, indent=2, sort_keys=True))
# and generate a helper script to massage scenario results into the format we'd
# like to query
with open('tools/run_tests/performance/massage_qps_stats.py', 'w') as P:
- with open(sys.argv[0]) as my_source:
- for line in my_source:
- if line[0] != '#': break
- for line in my_source:
- if line[0] == '#':
- print >>P, line.rstrip()
- break
- for line in my_source:
- if line[0] != '#':
- break
- print >>P, line.rstrip()
-
- print >>P
- print >>P, '# Autogenerated by tools/codegen/core/gen_stats_data.py'
- print >>P
-
- print >>P, 'import massage_qps_stats_helpers'
-
- print >>P, 'def massage_qps_stats(scenario_result):'
- print >>P, ' for stats in scenario_result["serverStats"] + scenario_result["clientStats"]:'
- print >>P, ' if "coreStats" not in stats: return'
- print >>P, ' core_stats = stats["coreStats"]'
- print >>P, ' del stats["coreStats"]'
- for counter in inst_map['Counter']:
- print >>P, ' stats["core_%s"] = massage_qps_stats_helpers.counter(core_stats, "%s")' % (counter.name, counter.name)
- for i, histogram in enumerate(inst_map['Histogram']):
- print >>P, ' h = massage_qps_stats_helpers.histogram(core_stats, "%s")' % histogram.name
- print >>P, ' stats["core_%s"] = ",".join("%%f" %% x for x in h.buckets)' % histogram.name
- print >>P, ' stats["core_%s_bkts"] = ",".join("%%f" %% x for x in h.boundaries)' % histogram.name
- for pctl in RECORD_EXPLICIT_PERCENTILES:
- print >>P, ' stats["core_%s_%dp"] = massage_qps_stats_helpers.percentile(h.buckets, %d, h.boundaries)' % (
- histogram.name, pctl, pctl)
+ with open(sys.argv[0]) as my_source:
+ for line in my_source:
+ if line[0] != '#': break
+ for line in my_source:
+ if line[0] == '#':
+ print >> P, line.rstrip()
+ break
+ for line in my_source:
+ if line[0] != '#':
+ break
+ print >> P, line.rstrip()
+
+ print >> P
+ print >> P, '# Autogenerated by tools/codegen/core/gen_stats_data.py'
+ print >> P
+
+ print >> P, 'import massage_qps_stats_helpers'
+
+ print >> P, 'def massage_qps_stats(scenario_result):'
+ print >> P, ' for stats in scenario_result["serverStats"] + scenario_result["clientStats"]:'
+ print >> P, ' if "coreStats" not in stats: return'
+ print >> P, ' core_stats = stats["coreStats"]'
+ print >> P, ' del stats["coreStats"]'
+ for counter in inst_map['Counter']:
+ print >> P, ' stats["core_%s"] = massage_qps_stats_helpers.counter(core_stats, "%s")' % (
+ counter.name, counter.name)
+ for i, histogram in enumerate(inst_map['Histogram']):
+ print >> P, ' h = massage_qps_stats_helpers.histogram(core_stats, "%s")' % histogram.name
+ print >> P, ' stats["core_%s"] = ",".join("%%f" %% x for x in h.buckets)' % histogram.name
+ print >> P, ' stats["core_%s_bkts"] = ",".join("%%f" %% x for x in h.boundaries)' % histogram.name
+ for pctl in RECORD_EXPLICIT_PERCENTILES:
+ print >> P, ' stats["core_%s_%dp"] = massage_qps_stats_helpers.percentile(h.buckets, %d, h.boundaries)' % (
+ histogram.name, pctl, pctl)
with open('src/core/lib/debug/stats_data_bq_schema.sql', 'w') as S:
- columns = []
- for counter in inst_map['Counter']:
- columns.append(('%s_per_iteration' % counter.name, 'FLOAT'))
- print >>S, ',\n'.join('%s:%s' % x for x in columns)
-
+ columns = []
+ for counter in inst_map['Counter']:
+ columns.append(('%s_per_iteration' % counter.name, 'FLOAT'))
+ print >> S, ',\n'.join('%s:%s' % x for x in columns)