Skip to content

Commit dfeeafd

Browse files
authored
Count each runner's simulation time separately (#333)
A model built once and simulated several ways - an FMU handed to several tools, or a wasm artifact run as a simulation, as FMI 3.0 ME and as CS - wrote the same exectime into every one of its branch tables, because exectime is the wall clock of the whole run of the model. The overview therefore gave wasm-jit, wasm-jit-me and wasm-jit-cs one identical execution time that was really all three of them added together. Only the simulation and the verification differ between the runners; everything up to the build is shared. Each runner now reports the shared part plus what it alone simulated and verified. testmodel.py records a simwall beside sim for that subtraction: sim is what the tool says it spent, which for the artifact runners is omc's timeSimulation and leaves out the loading around it, and that overhead would otherwise land in the shared part and be counted once per runner. The overview's branch table also gains a simulation time and a number of verified models, so the two figures that differ between runners of the same artifact can be read directly: | Branch | Version | Build time | Execution time | Simulation time | # Simulate | # Verify | # Total | | --- | --- | --- | --- | --- | --- | --- | --- | Rows already in the database keep the exectime they were written with; the new columns are correct for them, since simulate and finalphase have always been per runner. Assisted-by: Claude Opus 5 (1M context)
1 parent cdb2be5 commit dfeeafd

4 files changed

Lines changed: 38 additions & 5 deletions

File tree

‎overview.html.tpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
</table>
2121
<h2>Tested branches</h2>
2222
<table>
23-
<tr><th>Branch</th><th>Version</th><th>Build time</th><th>Execution time</th><th># Simulate</th><th># Total</th></tr>
23+
<tr><th>Branch</th><th>Version</th><th>Build time</th><th>Execution time</th><th>Simulation time</th><th># Simulate</th><th># Verify</th><th># Total</th></tr>
2424
#branches#
2525
</table>
2626
#entries#

‎report.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838

3939
nmodels = {}
4040
nsimulate = {}
41+
nverify = {}
4142
exectime = {}
43+
simtime = {}
4244

4345
missing_branches = []
4446
for branch in branches:
@@ -77,7 +79,9 @@
7779
branch_nmodels += 1
7880
nmodels[branch] = branch_nmodels
7981
nsimulate[branch] = 0
82+
nverify[branch] = 0
8083
exectime[branch] = 0.0
84+
simtime[branch] = 0.0
8185

8286
entries = ""
8387
# removing missing branches
@@ -131,6 +135,7 @@ def checkEqual(iterator):
131135
entries += '<td%s><a%s>%s%s</a></td>' % (' class="warning"' if old_vs and old_vs[i]>vs[i] else (' class="better"' if old_vs and old_vs[i]<vs[i] else ""),' class="dot"' if diff_text else "",vs[i],('<span class="tooltip">%s</span>' % diff_text) if diff_text else "")
132136
entries += "</tr>"
133137
nsimulate[branch] += vs[6]
138+
nverify[branch] += vs[7]
134139
if old_vs:
135140
old_vs = [max(vs[i], old_vs[i]) for i in range(0, len(vs))]
136141
else:
@@ -144,15 +149,17 @@ def checkEqual(iterator):
144149
entries += '<tr><td><a href="%s/%s/%s.html">%s</a></td>' % (branch,lib,lib,branch)
145150
entries += ("<td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n" % (friendlyStr(sums[0]),friendlyStr(sums[1]),friendlyStr(sums[2]),friendlyStr(sums[3]),friendlyStr(sums[4]),friendlyStr(sums[5]),friendlyStr(sums[6]),friendlyStr(sums[7]),friendlyStr(sums[8])))
146151
exectime[branch] += sums[0]
152+
simtime[branch] += sums[7]
147153
entries += "</table>\n"
148154
# print(sorted(list(libs[lib])))
149155

150156
nummodels = sum(len(l) for l in libs.values())
151-
branches_lines = [("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td%s>%d</td><td>%d</td></tr>\n" % (html.escape(branch), html.escape(
157+
branches_lines = [("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td%s>%d</td><td>%d</td><td>%d</td></tr>\n" % (html.escape(branch), html.escape(
152158
(cursor.execute("SELECT omcversion FROM omcversion WHERE date=? AND branch=?", (max(dates[branch][lib] for lib in libnames),branch)).fetchone() or ["unknown"])[0]
153-
), html.escape(dates_str[branch]), friendlyStr(exectime[branch]),
159+
), html.escape(dates_str[branch]), friendlyStr(exectime[branch]), friendlyStr(simtime[branch]),
154160
" class=\"warning\"" if nummodels!=nmodels[branch] else "",
155161
nsimulate[branch],
162+
nverify[branch],
156163
nmodels[branch]
157164
)) for branch in branches]
158165
template = open("overview.html.tpl").read()

‎test.py‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,26 @@ def phaseWithoutSimulator(data):
991991
"""
992992
return min(data.get("phase") or 0, BUILD_PHASE)
993993

994+
def simulatedTime(simulated):
995+
"""The wall clock simulating and verifying once cost.
996+
997+
An older result file has no simwall and only says what the tool spent.
998+
"""
999+
sim = simulated.get("simwall")
1000+
if sim is None:
1001+
sim = simulated.get("sim") or 0.0
1002+
return sim + ((simulated.get("diff") or {}).get("time") or 0.0)
1003+
1004+
def runnerExecTime(data, simulated):
1005+
"""The wall clock one runner of an FMU or of an artifact cost.
1006+
1007+
exectime is the whole run of the model, and all but the simulations is shared
1008+
by its runners, so each reports the shared part plus only its own simulation.
1009+
"""
1010+
runners = [data] + list((data.get("simulators") or {}).values())
1011+
shared_time = (data.get("exectime") or 0.0) - sum(simulatedTime(r) for r in runners)
1012+
return max(0.0, shared_time) + simulatedTime(simulated)
1013+
9941014
def resultValues(model, libname, data, simulator=None):
9951015
"""One row of a branch table.
9961016
@@ -1005,7 +1025,7 @@ def resultValues(model, libname, data, simulator=None):
10051025
return (testRunStartTimeAsEpoch,
10061026
libname,
10071027
model,
1008-
data.get("exectime") or 0.0,
1028+
runnerExecTime(data, simulated),
10091029
data.get("frontend") or 0.0,
10101030
data.get("backend") or 0.0,
10111031
data.get("simcode") or 0.0,

‎testmodel.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ def target(res):
236236
"templates":None,
237237
"build":None,
238238
"sim":None,
239+
"simwall":None, # Wall clock; sim is what the tool says it spent
239240
"simcold":None,
240241
"diff":None,
241242
"phase":0,
@@ -779,9 +780,11 @@ def simElapsed():
779780
else:
780781
res = checkOutputTimeout("(rm -f %s.pipe ; mkfifo %s.pipe ; head -c 1048576 < %s.pipe >> %s & %s > %s.pipe 2>&1)" % (conf["fileName"],conf["fileName"],conf["fileName"],simFile,cmd,conf["fileName"]), conf["ulimitExe"], conf)
781782
execstat["sim"] = simElapsed()
783+
execstat["simwall"] = monotonic()-start
782784
execstat["phase"] = 6
783785
except TimeoutError as e:
784786
execstat["sim"] = monotonic()-start
787+
execstat["simwall"] = execstat["sim"]
785788
# checkOutputTimeout raises TimeoutError for a command that fails as well as
786789
# for one that runs out of time, so this covers both.
787790
if len(runners) > 1:
@@ -917,7 +920,7 @@ def verifyAgainstReference(resFile, prefix, stat):
917920
# results down with it and leaves the others alone - the first one included,
918921
# see the TimeoutError handler above.
919922
for (name, command) in runners[1:]:
920-
stat = {"sim": None, "diff": None, "phase": 5}
923+
stat = {"sim": None, "simwall": None, "diff": None, "phase": 5}
921924
simulators[name] = stat
922925
simFileOther = os.path.abspath("../files/%s_%s.sim" % (conf["fileName"], name)).replace('\\','/')
923926
other = resultFile(name)
@@ -926,16 +929,19 @@ def verifyAgainstReference(resFile, prefix, stat):
926929
if useArtifact:
927930
res = simulateArtifact(name, command, other, simFileOther)
928931
stat["sim"] = res.get("timeSimulation") or (monotonic()-start)
932+
stat["simwall"] = monotonic()-start
929933
if not res.get("resultFile"):
930934
writeResult()
931935
continue
932936
else:
933937
simulateFmu(name, command, other, simFileOther)
934938
stat["sim"] = monotonic()-start
939+
stat["simwall"] = stat["sim"]
935940
stat["phase"] = 6
936941
verifyAgainstReference(other, artifactPrefix(name) + ".diff", stat)
937942
except TimeoutError as e:
938943
stat["sim"] = monotonic()-start
944+
stat["simwall"] = stat["sim"]
939945
with open(errFile, 'a+') as fp:
940946
fp.write("%s timed out simulating the %s\n" % (name, "artifact" if useArtifact else "FMU"))
941947
writeResult()

0 commit comments

Comments
 (0)