1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2017 gRPC authors. 3*cc02d7e2SAndroid Build Coastguard Worker# 4*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*cc02d7e2SAndroid Build Coastguard Worker# 8*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*cc02d7e2SAndroid Build Coastguard Worker# 10*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 15*cc02d7e2SAndroid Build Coastguard Worker 16*cc02d7e2SAndroid Build Coastguard Worker# Utilities for manipulating JSON data that represents microbenchmark results. 17*cc02d7e2SAndroid Build Coastguard Worker 18*cc02d7e2SAndroid Build Coastguard Workerimport os 19*cc02d7e2SAndroid Build Coastguard Worker 20*cc02d7e2SAndroid Build Coastguard Worker# template arguments and dynamic arguments of individual benchmark types 21*cc02d7e2SAndroid Build Coastguard Worker# Example benchmark name: "BM_UnaryPingPong<TCP, NoOpMutator, NoOpMutator>/0/0" 22*cc02d7e2SAndroid Build Coastguard Worker_BM_SPECS = { 23*cc02d7e2SAndroid Build Coastguard Worker "BM_UnaryPingPong": { 24*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture", "client_mutator", "server_mutator"], 25*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size", "response_size"], 26*cc02d7e2SAndroid Build Coastguard Worker }, 27*cc02d7e2SAndroid Build Coastguard Worker "BM_PumpStreamClientToServer": { 28*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 29*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 30*cc02d7e2SAndroid Build Coastguard Worker }, 31*cc02d7e2SAndroid Build Coastguard Worker "BM_PumpStreamServerToClient": { 32*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 33*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 34*cc02d7e2SAndroid Build Coastguard Worker }, 35*cc02d7e2SAndroid Build Coastguard Worker "BM_StreamingPingPong": { 36*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture", "client_mutator", "server_mutator"], 37*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size", "request_count"], 38*cc02d7e2SAndroid Build Coastguard Worker }, 39*cc02d7e2SAndroid Build Coastguard Worker "BM_StreamingPingPongMsgs": { 40*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture", "client_mutator", "server_mutator"], 41*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 42*cc02d7e2SAndroid Build Coastguard Worker }, 43*cc02d7e2SAndroid Build Coastguard Worker "BM_PumpStreamServerToClient_Trickle": { 44*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 45*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size", "bandwidth_kilobits"], 46*cc02d7e2SAndroid Build Coastguard Worker }, 47*cc02d7e2SAndroid Build Coastguard Worker "BM_PumpUnbalancedUnary_Trickle": { 48*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 49*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["cli_req_size", "svr_req_size", "bandwidth_kilobits"], 50*cc02d7e2SAndroid Build Coastguard Worker }, 51*cc02d7e2SAndroid Build Coastguard Worker "BM_ErrorStringOnNewError": { 52*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 53*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 54*cc02d7e2SAndroid Build Coastguard Worker }, 55*cc02d7e2SAndroid Build Coastguard Worker "BM_ErrorStringRepeatedly": { 56*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 57*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 58*cc02d7e2SAndroid Build Coastguard Worker }, 59*cc02d7e2SAndroid Build Coastguard Worker "BM_ErrorGetStatus": { 60*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 61*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 62*cc02d7e2SAndroid Build Coastguard Worker }, 63*cc02d7e2SAndroid Build Coastguard Worker "BM_ErrorGetStatusCode": { 64*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 65*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 66*cc02d7e2SAndroid Build Coastguard Worker }, 67*cc02d7e2SAndroid Build Coastguard Worker "BM_ErrorHttpError": { 68*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 69*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 70*cc02d7e2SAndroid Build Coastguard Worker }, 71*cc02d7e2SAndroid Build Coastguard Worker "BM_HasClearGrpcStatus": { 72*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 73*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 74*cc02d7e2SAndroid Build Coastguard Worker }, 75*cc02d7e2SAndroid Build Coastguard Worker "BM_IsolatedFilter": { 76*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture", "client_mutator"], 77*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 78*cc02d7e2SAndroid Build Coastguard Worker }, 79*cc02d7e2SAndroid Build Coastguard Worker "BM_HpackEncoderEncodeHeader": { 80*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 81*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["end_of_stream", "request_size"], 82*cc02d7e2SAndroid Build Coastguard Worker }, 83*cc02d7e2SAndroid Build Coastguard Worker "BM_HpackParserParseHeader": { 84*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 85*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 86*cc02d7e2SAndroid Build Coastguard Worker }, 87*cc02d7e2SAndroid Build Coastguard Worker "BM_CallCreateDestroy": { 88*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 89*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 90*cc02d7e2SAndroid Build Coastguard Worker }, 91*cc02d7e2SAndroid Build Coastguard Worker "BM_Zalloc": { 92*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 93*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 94*cc02d7e2SAndroid Build Coastguard Worker }, 95*cc02d7e2SAndroid Build Coastguard Worker "BM_PollEmptyPollset_SpeedOfLight": { 96*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 97*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size", "request_count"], 98*cc02d7e2SAndroid Build Coastguard Worker }, 99*cc02d7e2SAndroid Build Coastguard Worker "BM_StreamCreateSendInitialMetadataDestroy": { 100*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture"], 101*cc02d7e2SAndroid Build Coastguard Worker "dyn": [], 102*cc02d7e2SAndroid Build Coastguard Worker }, 103*cc02d7e2SAndroid Build Coastguard Worker "BM_TransportStreamSend": { 104*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 105*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 106*cc02d7e2SAndroid Build Coastguard Worker }, 107*cc02d7e2SAndroid Build Coastguard Worker "BM_TransportStreamRecv": { 108*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 109*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 110*cc02d7e2SAndroid Build Coastguard Worker }, 111*cc02d7e2SAndroid Build Coastguard Worker "BM_StreamingPingPongWithCoalescingApi": { 112*cc02d7e2SAndroid Build Coastguard Worker "tpl": ["fixture", "client_mutator", "server_mutator"], 113*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size", "request_count", "end_of_stream"], 114*cc02d7e2SAndroid Build Coastguard Worker }, 115*cc02d7e2SAndroid Build Coastguard Worker "BM_Base16SomeStuff": { 116*cc02d7e2SAndroid Build Coastguard Worker "tpl": [], 117*cc02d7e2SAndroid Build Coastguard Worker "dyn": ["request_size"], 118*cc02d7e2SAndroid Build Coastguard Worker }, 119*cc02d7e2SAndroid Build Coastguard Worker} 120*cc02d7e2SAndroid Build Coastguard Worker 121*cc02d7e2SAndroid Build Coastguard Worker 122*cc02d7e2SAndroid Build Coastguard Workerdef numericalize(s): 123*cc02d7e2SAndroid Build Coastguard Worker """Convert abbreviations like '100M' or '10k' to a number.""" 124*cc02d7e2SAndroid Build Coastguard Worker if not s: 125*cc02d7e2SAndroid Build Coastguard Worker return "" 126*cc02d7e2SAndroid Build Coastguard Worker if s[-1] == "k": 127*cc02d7e2SAndroid Build Coastguard Worker return float(s[:-1]) * 1024 128*cc02d7e2SAndroid Build Coastguard Worker if s[-1] == "M": 129*cc02d7e2SAndroid Build Coastguard Worker return float(s[:-1]) * 1024 * 1024 130*cc02d7e2SAndroid Build Coastguard Worker if 0 <= (ord(s[-1]) - ord("0")) <= 9: 131*cc02d7e2SAndroid Build Coastguard Worker return float(s) 132*cc02d7e2SAndroid Build Coastguard Worker assert "not a number: %s" % s 133*cc02d7e2SAndroid Build Coastguard Worker 134*cc02d7e2SAndroid Build Coastguard Worker 135*cc02d7e2SAndroid Build Coastguard Workerdef parse_name(name): 136*cc02d7e2SAndroid Build Coastguard Worker cpp_name = name 137*cc02d7e2SAndroid Build Coastguard Worker if "<" not in name and "/" not in name and name not in _BM_SPECS: 138*cc02d7e2SAndroid Build Coastguard Worker return {"name": name, "cpp_name": name} 139*cc02d7e2SAndroid Build Coastguard Worker rest = name 140*cc02d7e2SAndroid Build Coastguard Worker out = {} 141*cc02d7e2SAndroid Build Coastguard Worker tpl_args = [] 142*cc02d7e2SAndroid Build Coastguard Worker dyn_args = [] 143*cc02d7e2SAndroid Build Coastguard Worker if "<" in rest: 144*cc02d7e2SAndroid Build Coastguard Worker tpl_bit = rest[rest.find("<") + 1 : rest.rfind(">")] 145*cc02d7e2SAndroid Build Coastguard Worker arg = "" 146*cc02d7e2SAndroid Build Coastguard Worker nesting = 0 147*cc02d7e2SAndroid Build Coastguard Worker for c in tpl_bit: 148*cc02d7e2SAndroid Build Coastguard Worker if c == "<": 149*cc02d7e2SAndroid Build Coastguard Worker nesting += 1 150*cc02d7e2SAndroid Build Coastguard Worker arg += c 151*cc02d7e2SAndroid Build Coastguard Worker elif c == ">": 152*cc02d7e2SAndroid Build Coastguard Worker nesting -= 1 153*cc02d7e2SAndroid Build Coastguard Worker arg += c 154*cc02d7e2SAndroid Build Coastguard Worker elif c == ",": 155*cc02d7e2SAndroid Build Coastguard Worker if nesting == 0: 156*cc02d7e2SAndroid Build Coastguard Worker tpl_args.append(arg.strip()) 157*cc02d7e2SAndroid Build Coastguard Worker arg = "" 158*cc02d7e2SAndroid Build Coastguard Worker else: 159*cc02d7e2SAndroid Build Coastguard Worker arg += c 160*cc02d7e2SAndroid Build Coastguard Worker else: 161*cc02d7e2SAndroid Build Coastguard Worker arg += c 162*cc02d7e2SAndroid Build Coastguard Worker tpl_args.append(arg.strip()) 163*cc02d7e2SAndroid Build Coastguard Worker rest = rest[: rest.find("<")] + rest[rest.rfind(">") + 1 :] 164*cc02d7e2SAndroid Build Coastguard Worker if "/" in rest: 165*cc02d7e2SAndroid Build Coastguard Worker s = rest.split("/") 166*cc02d7e2SAndroid Build Coastguard Worker rest = s[0] 167*cc02d7e2SAndroid Build Coastguard Worker dyn_args = s[1:] 168*cc02d7e2SAndroid Build Coastguard Worker name = rest 169*cc02d7e2SAndroid Build Coastguard Worker assert name in _BM_SPECS, "_BM_SPECS needs to be expanded for %s" % name 170*cc02d7e2SAndroid Build Coastguard Worker assert len(dyn_args) == len(_BM_SPECS[name]["dyn"]) 171*cc02d7e2SAndroid Build Coastguard Worker assert len(tpl_args) == len(_BM_SPECS[name]["tpl"]) 172*cc02d7e2SAndroid Build Coastguard Worker out["name"] = name 173*cc02d7e2SAndroid Build Coastguard Worker out["cpp_name"] = cpp_name 174*cc02d7e2SAndroid Build Coastguard Worker out.update( 175*cc02d7e2SAndroid Build Coastguard Worker dict( 176*cc02d7e2SAndroid Build Coastguard Worker (k, numericalize(v)) 177*cc02d7e2SAndroid Build Coastguard Worker for k, v in zip(_BM_SPECS[name]["dyn"], dyn_args) 178*cc02d7e2SAndroid Build Coastguard Worker ) 179*cc02d7e2SAndroid Build Coastguard Worker ) 180*cc02d7e2SAndroid Build Coastguard Worker out.update(dict(zip(_BM_SPECS[name]["tpl"], tpl_args))) 181*cc02d7e2SAndroid Build Coastguard Worker return out 182*cc02d7e2SAndroid Build Coastguard Worker 183*cc02d7e2SAndroid Build Coastguard Worker 184*cc02d7e2SAndroid Build Coastguard Workerdef expand_json(js): 185*cc02d7e2SAndroid Build Coastguard Worker if not js: 186*cc02d7e2SAndroid Build Coastguard Worker raise StopIteration() 187*cc02d7e2SAndroid Build Coastguard Worker for bm in js["benchmarks"]: 188*cc02d7e2SAndroid Build Coastguard Worker if bm["name"].endswith("_stddev") or bm["name"].endswith("_mean"): 189*cc02d7e2SAndroid Build Coastguard Worker continue 190*cc02d7e2SAndroid Build Coastguard Worker context = js["context"] 191*cc02d7e2SAndroid Build Coastguard Worker if "label" in bm: 192*cc02d7e2SAndroid Build Coastguard Worker labels_list = [ 193*cc02d7e2SAndroid Build Coastguard Worker s.split(":") 194*cc02d7e2SAndroid Build Coastguard Worker for s in bm["label"].strip().split(" ") 195*cc02d7e2SAndroid Build Coastguard Worker if len(s) and s[0] != "#" 196*cc02d7e2SAndroid Build Coastguard Worker ] 197*cc02d7e2SAndroid Build Coastguard Worker for el in labels_list: 198*cc02d7e2SAndroid Build Coastguard Worker el[0] = el[0].replace("/iter", "_per_iteration") 199*cc02d7e2SAndroid Build Coastguard Worker labels = dict(labels_list) 200*cc02d7e2SAndroid Build Coastguard Worker else: 201*cc02d7e2SAndroid Build Coastguard Worker labels = {} 202*cc02d7e2SAndroid Build Coastguard Worker # TODO(jtattermusch): grabbing kokoro env values shouldn't be buried 203*cc02d7e2SAndroid Build Coastguard Worker # deep in the JSON conversion logic. 204*cc02d7e2SAndroid Build Coastguard Worker # Link the data to a kokoro job run by adding 205*cc02d7e2SAndroid Build Coastguard Worker # well known kokoro env variables as metadata for each row 206*cc02d7e2SAndroid Build Coastguard Worker row = { 207*cc02d7e2SAndroid Build Coastguard Worker "jenkins_build": os.environ.get("KOKORO_BUILD_NUMBER", ""), 208*cc02d7e2SAndroid Build Coastguard Worker "jenkins_job": os.environ.get("KOKORO_JOB_NAME", ""), 209*cc02d7e2SAndroid Build Coastguard Worker } 210*cc02d7e2SAndroid Build Coastguard Worker row.update(context) 211*cc02d7e2SAndroid Build Coastguard Worker row.update(bm) 212*cc02d7e2SAndroid Build Coastguard Worker row.update(parse_name(row["name"])) 213*cc02d7e2SAndroid Build Coastguard Worker row.update(labels) 214*cc02d7e2SAndroid Build Coastguard Worker yield row 215