Skip to content
Closed

test #47

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ jobs:
dub run -- \
--base-dmd "$RUNNER_TEMP/base/dmd/$built" \
--head-dmd "$RUNNER_TEMP/head/dmd/$built" \
--base-phobos "$RUNNER_TEMP/base/phobos" \
--head-phobos "$RUNNER_TEMP/head/phobos" \
--base-sha "${{ steps.refs.outputs.base }}" \
--head-sha "${{ steps.refs.outputs.head }}" \
--pr "${{ github.event.pull_request.number || 0 }}" \
Expand Down
24 changes: 22 additions & 2 deletions compiler/src/dmd/root/aav.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,28 @@ nothrow:

private size_t hash(size_t a) pure nothrow @nogc @safe
{
a ^= (a >> 20) ^ (a >> 12);
return a ^ (a >> 7) ^ (a >> 4);
// Keys are pointers: 16-byte aligned (low bits zero) and roughly sequential
// from the bump allocator, so they are highly correlated. The bucket index
// is `hash & (b_length - 1)`, i.e. the low bits, so the mix must spread
// entropy all the way down. This is the murmur3 fmix full-avalanche
// finalizer (fmix64 on 64-bit hosts, fmix32 on 32-bit).
static if (size_t.sizeof == 8)
{
a ^= a >> 33;
a *= 0xff51afd7ed558ccd;
a ^= a >> 33;
a *= 0xc4ceb9fe1a85ec53;
a ^= a >> 33;
}
else
{
a ^= a >> 16;
a *= 0x85ebca6b;
a ^= a >> 13;
a *= 0xc2b2ae35;
a ^= a >> 16;
}
return a;
}

private struct KeyValueTemplate(K,V)
Expand Down
12 changes: 8 additions & 4 deletions tools/perfrunner/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ version (unittest) {} else
int main(string[] args)
{
string baseDmd, headDmd, baseSha, headSha, hostDmd;
string basePhobos, headPhobos;
string os = "ubuntu-latest";
string outPath = "results.json";
long pr;

auto help = getopt(args,
"base-dmd", "path to the base (merge-base) dmd binary", &baseDmd,
"head-dmd", "path to the head (PR) dmd binary", &headDmd,
"base-phobos", "path to the base phobos checkout (enables Phobos workload)", &basePhobos,
"head-phobos", "path to the head phobos checkout (enables Phobos workload)", &headPhobos,
"base-sha", "base commit sha (metadata)", &baseSha,
"head-sha", "head commit sha (metadata)", &headSha,
"pr", "pull request number (metadata)", &pr,
Expand All @@ -46,13 +49,14 @@ int main(string[] args)
auto tmp = buildPath(tempDir, "perfrunner");
mkdirRecurse(tmp);

auto base = measure(baseDmd, workload, tmp, "base");
auto head = measure(headDmd, workload, tmp, "head");
auto base = measure(baseDmd, workload, basePhobos, tmp, "base");
auto head = measure(headDmd, workload, headPhobos, tmp, "head");

MetricResult[] metrics;
foreach (def; initials)
metrics ~= MetricResult(def.id, def.label, def.unit, def.method,
base[def.id], head[def.id]);
if (def.id in base && def.id in head)
metrics ~= MetricResult(def.id, def.label, def.unit, def.method,
base[def.id], head[def.id]);

auto rep = Report(baseSha, "merge-base", headSha, pr, os, hostDmd, metrics);
write(outPath, render(rep));
Expand Down
20 changes: 13 additions & 7 deletions tools/perfrunner/source/cachegrind.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import std.array : split;
import std.conv : to;
import std.file : readText;
import std.path : buildPath;
import std.process : execute;
import std.process : execute, Config;
import std.string : lineSplitter, strip;

long parseInstructions(string cgout)
Expand All @@ -16,19 +16,25 @@ long parseInstructions(string cgout)
throw new Exception("could not find 'summary:' line in cachegrind output");
}

// Compile the workload under cachegrind
long instructions(string dmd, string[] dflags, string workload, string tmp, string tag)
// Run `dmd args...` under cachegrind (optionally from `workDir`) and return
// the retired-instruction count.
long instructionsAt(string dmd, string[] args, string tmp, string tag, string workDir = null)
{
auto obj = buildPath(tmp, tag ~ ".o");
auto cgOut = buildPath(tmp, tag ~ ".cgout");
auto cmd = ["valgrind", "--tool=cachegrind", "--cachegrind-out-file=" ~ cgOut,
dmd, "-c"] ~ dflags ~ [workload, "-of=" ~ obj];
auto r = execute(cmd);
auto cmd = ["valgrind", "--tool=cachegrind", "--cachegrind-out-file=" ~ cgOut, dmd] ~ args;
auto r = execute(cmd, null, Config.none, size_t.max, workDir);
if (r.status != 0)
throw new Exception("cachegrind failed:\n" ~ r.output);
return parseInstructions(readText(cgOut));
}

// Compile the workload under cachegrind
long instructions(string dmd, string[] dflags, string workload, string tmp, string tag)
{
auto obj = buildPath(tmp, tag ~ ".o");
return instructionsAt(dmd, ["-c"] ~ dflags ~ [workload, "-of=" ~ obj], tmp, tag);
}

unittest
{
auto sample = "events: Ir\nfn=(1) main\n5 100\nsummary: 1234500000\n";
Expand Down
36 changes: 29 additions & 7 deletions tools/perfrunner/source/metrics.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import std.file : copy, exists, getSize, remove;
import std.path : buildPath;
import std.regex : ctRegex, matchFirst;

import std.process : execute;
import std.process : execute, Config;

import cachegrind : instructions;
import cachegrind : instructions, instructionsAt;

struct MetricDef
{
Expand All @@ -24,19 +24,35 @@ immutable MetricDef[] initials = [
MetricDef("dmd_binary_size", "dmd binary size (stripped)", "bytes", "stat"),
MetricDef("hello_binary_size", "hello binary size", "bytes", "stat"),
MetricDef("hello_max_rss", "peak RSS (compile hello.d)", "kb", "time -v"),
// Symbol-heavy front-end workload: analyse all of Phobos without codegen.
MetricDef("compile_phobos_instr", "compile Phobos (instr)", "count", "cachegrind"),
MetricDef("phobos_max_rss", "peak RSS (Phobos)", "kb", "time -v"),
];

// Measure every metric for one dmd binary. `tag` ("base"/"head")
// keeps the two runs' temp files apart
long[string] measure(string dmd, string workload, string tmp, string tag)
// dmd arguments for the Phobos workload, run with the phobos dir as CWD so the
// compiler's own dmd.conf resolves std/core imports. `-o-` keeps it front-end
// only (no backend/codegen), `-i=std` forces full semantic of every std module.
private immutable string[] phobosArgs = ["-o-", "-i=std", "-preview=dip1000", "std/package.d"];

// Measure every metric for one dmd binary. `tag` ("base"/"head") keeps the two
// runs' temp files apart. The Phobos metrics are only measured when `phobosDir`
// is given (so local hello-only runs still work).
long[string] measure(string dmd, string workload, string phobosDir, string tmp, string tag)
{
return [
long[string] m = [
"compile_hello_debug_instr": instructions(dmd, [], workload, tmp, tag ~ "-dbg"),
"compile_hello_release_instr": instructions(dmd, ["-O", "-release"], workload, tmp, tag ~ "-rel"),
"dmd_binary_size": strippedSize(dmd, buildPath(tmp, tag ~ "-dmd")),
"hello_binary_size": helloSize(dmd, workload, tmp, tag),
"hello_max_rss": maxRss(dmd, workload, tmp, tag),
];

if (phobosDir.length)
{
m["compile_phobos_instr"] = instructionsAt(dmd, phobosArgs.dup, tmp, tag ~ "-phobos", phobosDir);
m["phobos_max_rss"] = maxRssCmd([dmd] ~ phobosArgs.dup, phobosDir);
}
return m;
}

// Byte size of `binary`
Expand Down Expand Up @@ -71,7 +87,13 @@ private void strip(string path)
private long maxRss(string dmd, string workload, string tmp, string tag)
{
auto obj = buildPath(tmp, tag ~ "-rss.o");
auto r = execute(["/usr/bin/time", "-v", dmd, "-c", workload, "-of=" ~ obj]);
return maxRssCmd([dmd, "-c", workload, "-of=" ~ obj]);
}

// Peak RSS (KiB) of running `cmd` under /usr/bin/time, optionally from `workDir`.
private long maxRssCmd(string[] cmd, string workDir = null)
{
auto r = execute(["/usr/bin/time", "-v"] ~ cmd, null, Config.none, size_t.max, workDir);
if (r.status != 0)
throw new Exception("/usr/bin/time failed:\n" ~ r.output);
return parseMaxRss(r.output);
Expand Down
Loading