// function type is A (e.g. String) sclass FunctionTimings { Map data = syncMap(); meta-for Runnable also as RunnableWithExceptions { void do aka time(A function, Runnable r) ctex { if (r == null) ret; long time = nanoTime(); try { r.run(); } finally { time = nanoTime()-time; saveTiming(function, time); } } } void saveTiming(A function, long time) { Average avg = syncMapGetOrCreate(data, function, -> new Average); avg.add(time); } Map get() { ret cloneMap(data); } void reset aka clear() { data.clear(); } // as multi-line string, sorted alphabetically S render() { ret lines(ciSorted(map(get(), (f, avg) -> functionToString(f) + ": " + n2(iround(nsToMicroseconds(avg!))) + " " + microSymbol() + "s (" + n2(iround(avg.n())) + ")"))); } S functionToString(A f) { ret firstToUpper(str(f)); } }