Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Benchmark analysis #2293

Merged
merged 32 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a5ba3fa
first pass at benchmark analysis
bdemann Nov 27, 2024
9ec3453
use baseline weighted efficiency score
bdemann Nov 27, 2024
3d743f2
functional pass
bdemann Nov 27, 2024
d60615d
make functions
bdemann Nov 27, 2024
660cf29
top level functions
bdemann Nov 27, 2024
f6dee6f
move into it's own folder
bdemann Nov 27, 2024
b33a232
separate into individual files
bdemann Nov 27, 2024
49d96bf
clean up
bdemann Dec 2, 2024
6f3da81
update formatting
bdemann Dec 2, 2024
e26f645
attempt to use only lower percentiles
bdemann Dec 2, 2024
abc4f92
filter out methods longer than max instructions
bdemann Dec 13, 2024
67543b0
remove sd analysis since data is not a normal distribution
bdemann Dec 13, 2024
e999798
find missing or wrong versions
bdemann Dec 13, 2024
517f990
update status
bdemann Dec 13, 2024
b78c452
clean up
bdemann Dec 16, 2024
8d640c0
update into table
bdemann Dec 17, 2024
546fa3a
progress
bdemann Dec 17, 2024
e03b15f
pull count and bwe score out of the table
bdemann Dec 17, 2024
631ec1e
split experimental and stable
bdemann Dec 17, 2024
b91e915
html table
bdemann Dec 17, 2024
0ed1b57
split out markdown generation
bdemann Dec 17, 2024
e507126
clean up markdown report
bdemann Dec 17, 2024
133a4be
clean up
bdemann Dec 17, 2024
f2b556a
add js doc
bdemann Dec 17, 2024
fc69d3a
add indentation
bdemann Dec 17, 2024
536bce0
correct pluralization
bdemann Dec 17, 2024
fea5fea
add benchmark analysis to the benchmark workflow
bdemann Dec 17, 2024
4234f76
make extractor more declarative
bdemann Dec 17, 2024
16da7a8
pr fixes
bdemann Dec 18, 2024
aa1e33d
use semver to sort our benchmark versions
bdemann Dec 18, 2024
0604fcf
install dependencies
bdemann Dec 18, 2024
5cfae40
use npm install over npm ci for now
bdemann Dec 18, 2024
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
42 changes: 42 additions & 0 deletions benchmark_stats.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"0.25.0-dev": {
"stable": {
"count": 611,
"mean": 120237704.94599018,
"median": 1011216,
"standardDeviation": 1266731659.1596396,
"min": 163759,
"max": 19060732880,
"baselineWeightedEfficiencyScore": 12425390.694599018
},
"experimental": {
"count": 745,
"mean": 1026538663.6483221,
"median": 8922860,
"standardDeviation": 3031934484.2442517,
"min": 84524,
"max": 18426067752,
"baselineWeightedEfficiencyScore": 105381438.76483223
}
},
"0.25.0-pre-bifurcation": {
"stable": {
"count": 624,
"mean": 101374357.53525642,
"median": 1040987,
"standardDeviation": 1192914154.3810272,
"min": 155606,
"max": 18226207933,
"baselineWeightedEfficiencyScore": 10543095.453525642
},
"experimental": {
"count": 686,
"mean": 1153922654.5932944,
"median": 8920551.5,
"standardDeviation": 3168782029.724511,
"min": 83475,
"max": 18422514685,
"baselineWeightedEfficiencyScore": 118118515.90932944
}
}
}
177 changes: 177 additions & 0 deletions benchmark_stats.md
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Benchmark Results
lastmjs marked this conversation as resolved.
Show resolved Hide resolved

## Version `0.25.0-dev`

<table>
<tr>
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
<th></th>
<th colspan="2">Stable</th>
<th colspan="2">Experimental</th>
</tr>
<tr>
<th>Metric</th>
<th>Score</th>
<th>Change</th>
<th>Score</th>
<th>Change</th>
</tr>
<td>Baseline Weighted Efficiency</td>
<td>12_425_390</td>
<td><span style="color: red">17.85%</span></td>
<td>105_381_438</td>
<td><span style="color: green">-10.78%</span></td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<tr>
<th></th>
<th>Count</th>
<th></th>
<th>Count</th>
<th></th>
</tr>
<tr>
<td>Method Executions</td>
<td>611</td>
<td><span style="color: green">-2.08%</span></td>
<td>745</td>
<td><span style="color: red">8.60%</span></td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<tr>
<th></th>
<th>Number of Instructions</th>
<th></th>
<th>Number of Instructions</th>
<th></th>
</tr>
<tr>
<td>Mean</td>
<td>120_237_704</td>
<td><span style="color: red">18.61%</span></td>
<td>1_026_538_663</td>
<td><span style="color: green">-11.04%</span></td>
</tr>
<tr>
<td>Median</td>
<td>1_011_216</td>
<td><span style="color: green">-2.86%</span></td>
<td>8_922_860</td>
<td><span style="color: red">0.03%</span></td>
</tr>
<tr>
<td>Standard Deviation</td>
<td>1_266_731_659</td>
<td><span style="color: red">6.19%</span></td>
<td>3_031_934_484</td>
<td><span style="color: green">-4.32%</span></td>
</tr>
<tr>
<td>Min</td>
<td>163_759</td>
<td><span style="color: red">5.24%</span></td>
<td>84_524</td>
<td><span style="color: red">1.26%</span></td>
</tr>
<tr>
<td>Max</td>
<td>19_060_732_880</td>
<td><span style="color: red">4.58%</span></td>
<td>18_426_067_752</td>
<td><span style="color: red">0.02%</span></td>
</tr>

</table>

## Version `0.25.0-pre-bifurcation`

<table>
<tr>
<th></th>
<th colspan="2">Stable</th>
<th colspan="2">Experimental</th>
</tr>
<tr>
<th>Metric</th>
<th>Score</th>
<th>Change</th>
<th>Score</th>
<th>Change</th>
</tr>
<td>Baseline Weighted Efficiency</td>
<td>10_543_095</td>
<td>0.00%</td>
<td>118_118_515</td>
<td>0.00%</td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<tr>
<th></th>
<th>Count</th>
<th></th>
<th>Count</th>
<th></th>
</tr>
<tr>
<td>Method Executions</td>
<td>624</td>
<td>0.00%</td>
<td>686</td>
<td>0.00%</td>
</tr>
<tr>
<td colspan="5">&nbsp;</td>
</tr>
<tr>
<th></th>
<th>Number of Instructions</th>
<th></th>
<th>Number of Instructions</th>
<th></th>
</tr>
<tr>
<td>Mean</td>
<td>101_374_357</td>
<td>0.00%</td>
<td>1_153_922_654</td>
<td>0.00%</td>
</tr>
<tr>
<td>Median</td>
<td>1_040_987</td>
<td>0.00%</td>
<td>8_920_551</td>
<td>0.00%</td>
</tr>
<tr>
<td>Standard Deviation</td>
<td>1_192_914_154</td>
<td>0.00%</td>
<td>3_168_782_029</td>
<td>0.00%</td>
</tr>
<tr>
<td>Min</td>
<td>155_606</td>
<td>0.00%</td>
<td>83_475</td>
<td>0.00%</td>
</tr>
<tr>
<td>Max</td>
<td>18_226_207_933</td>
<td>0.00%</td>
<td>18_422_514_685</td>
<td>0.00%</td>
</tr>

</table>

---

_Report generated automatically by Azle benchmark tools_
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
88 changes: 88 additions & 0 deletions scripts/analyze_benchmarks/extractor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { readFile } from 'fs/promises';

export type BenchmarkEntry = {
instructions: { __bigint__: string };
method_name: string;
timestamp: { __bigint__: string };
};

type CanisterBenchmark = {
current?: {
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
version: string;
benchmarks: BenchmarkEntry[];
};
previous: {
version: string;
benchmarks: BenchmarkEntry[];
};
};

type BenchmarksJson = {
[canisterName: string]: CanisterBenchmark;
};

/**
* Extracts benchmark entries from multiple files and groups them by version
* @param files Array of file paths to process
* @returns A record mapping version strings to arrays of benchmark entries
*/
export async function extractBenchmarksEntriesFromFiles(
files: string[]
): Promise<Record<string, BenchmarkEntry[]>> {
const versionEntriesArrays = await Promise.all(
files.map(extractBenchmarkEntries)
);
const versionEntries = versionEntriesArrays.flat();

return groupEntriesByVersion(versionEntries);
}

/**
* Extracts benchmark entries from a single file
* @param file Path to the benchmark file
* @returns Array of tuples containing version and benchmark entry pairs
*/
async function extractBenchmarkEntries(
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
file: string
): Promise<Array<[string, BenchmarkEntry]>> {
const data: BenchmarksJson = JSON.parse(await readFile(file, 'utf-8'));

return Object.values(data).flatMap((canisterData) => {
const currentEntries = canisterData.current
? canisterData.current.benchmarks.map(
(benchmark) =>
[canisterData.current!.version, benchmark] as [
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
string,
BenchmarkEntry
]
)
: [];

const previousEntries = canisterData.previous.benchmarks.map(
(benchmark) =>
[canisterData.previous.version, benchmark] as [
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
string,
BenchmarkEntry
]
);

return [...currentEntries, ...previousEntries];
});
}

/**
* Groups benchmark entries by their version
* @param entries Array of version and benchmark entry pairs
* @returns A record mapping version strings to arrays of benchmark entries
*/
function groupEntriesByVersion(
entries: Array<[string, BenchmarkEntry]>
): Record<string, BenchmarkEntry[]> {
return entries.reduce(
(acc, [version, entry]) => ({
...acc,
[version]: [...(acc[version] ?? []), entry]
}),
{} as Record<string, BenchmarkEntry[]>
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
);
}
37 changes: 37 additions & 0 deletions scripts/analyze_benchmarks/file_finder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { readdir, stat } from 'fs/promises';
import { join } from 'path';

/**
* Recursively finds all benchmark.json files in a directory and its subdirectories
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
* @param dir Directory path to search
* @returns Array of full paths to benchmark.json files
lastmjs marked this conversation as resolved.
Show resolved Hide resolved
*/
export async function findBenchmarkFiles(dir: string): Promise<string[]> {
if (dir.includes('node_modules')) {
return [];
}
const items = await readdir(dir);
const itemResults = await Promise.all(
items.map((item) => processDirectoryItem(dir, item))
);
return itemResults.flat();
}

/**
* Processes a single item in a directory to determine if it's a benchmark file
* @param dir Parent directory path
* @param item Name of the item to process
* @returns Array of paths to benchmark files (empty if item is not a benchmark file)
*/
async function processDirectoryItem(
dir: string,
item: string
): Promise<string[]> {
const fullPath = join(dir, item);

const statInfo = await stat(fullPath);
if (statInfo.isDirectory()) {
return findBenchmarkFiles(fullPath);
}
return item === 'benchmarks.json' ? [fullPath] : [];
}
Loading
Loading