diff --git a/benchmarks/perf.nim b/benchmarks/perf.nim new file mode 100644 index 00000000..a9b2577b --- /dev/null +++ b/benchmarks/perf.nim @@ -0,0 +1,49 @@ +# Simple utils for controlling perf tracing through fifos. +# After creating ack and control fifos with mkfifo, you can use this with: +# +# perf record -g \ +# --delay -1 \ +# --control fifo:./perf-ctl,./perf-ack \ +# --call-graph dwarf \ +# -F 99 \ +# -o perf.data -- [command] + +import std/strformat +import std/strutils + +import pkg/questionable/results + +type Perf* = object + ctl_file: File + ack_file: File + +proc attach*(Perf: type, ctl_fifo: string, ack_fifo: string): ?!Perf = + var perf: Perf + if not open(perf.ctl_file, ctl_fifo, fmWrite): + return failure("Failed to open ctl fifo") + if not open(perf.ack_file, ack_fifo, fmRead): + return failure("Failed to open ack fifo") + + success(perf) + +proc detach*(self: Perf) = + self.ctl_file.close() + self.ack_file.close() + +proc send*(self: Perf, cmd: string): ?!void = + self.ctl_file.write(cmd) + self.ctl_file.flushFile() + + let response = self.ack_file.readLine() + # Ideally equality should work, but in practice we get some garbage + # characters sometimes. + if not ("ack" in response): + return failure(&"Error {response} received from perf") + + success() + +proc perfOn*(self: Perf): ?!void = + send(self, "enable") + +proc perfOff*(self: Perf): ?!void = + send(self, "disable") diff --git a/benchmarks/repostore_rw_bench.nim b/benchmarks/repostore_rw_bench.nim index 42a3b585..69b08932 100644 --- a/benchmarks/repostore_rw_bench.nim +++ b/benchmarks/repostore_rw_bench.nim @@ -11,23 +11,7 @@ import pkg/codex/merkletree/codex import pkg/codex/manifest import pkg/codex/stores/[filestore, repostore] -let - PR_TASK_PERF_EVENTS_DISABLE {. - importc: "PR_TASK_PERF_EVENTS_DISABLE", header: "" - .}: cint - PR_TASK_PERF_EVENTS_ENABLE {. - importc: "PR_TASK_PERF_EVENTS_ENABLE", header: "" - .}: cint - -proc prctl( - option: cint, args: varargs[culong] -): cint {.importc: "prctl", header: "".} - -proc perfOn() = - assert prctl(PR_TASK_PERF_EVENTS_ENABLE) == 0 - -proc perfOff() = - assert prctl(PR_TASK_PERF_EVENTS_DISABLE) == 0 +import ./perf const NBlocks = 163_840 @@ -118,6 +102,12 @@ proc readData( proc runRepostoreBench( dataset: Dataset ): Future[void] {.async: (raises: [CatchableError]).} = + let perf = Perf.attach("./perf-ctl", "./perf-ack").expect( + "failed to locate perf ctl/ack files" + ) + + perf.perfOff().expect("failed to disable perf") + let dir = createTempDir("repostore-bench", "") store = newRepostore(dir) @@ -129,13 +119,19 @@ proc runRepostoreBench( benchmark "repostore write data": await writeData(dataset, store) + perf.perfOn().expect("failed to enable perf") + benchmark "repostore read data": await writeData(dataset, store) proc runFilestoreBench( dataset: Dataset ): Future[void] {.async: (raises: [CatchableError]).} = - perfOff() + let perf = Perf.attach("./perf-ctl", "./perf-ack").expect( + "failed to locate perf ctl/ack files" + ) + + perf.perfOff().expect("failed to disable perf") let dir = createTempDir("filestore-bench", "") @@ -148,11 +144,11 @@ proc runFilestoreBench( benchmark "filestore write data": await writeData(dataset, store) - perfOn() + perf.perfOn().expect("failed to enable perf") benchmark "filestore read data": await readData(dataset, store) let dataset = makeDataset(NBlocks, BlockSize).tryGet() -# waitFor runRepostoreBench(dataset) -waitFor runFilestoreBench(dataset) +waitFor runRepostoreBench(dataset) +#waitFor runFilestoreBench(dataset)