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

feat: add support for memory report #7

Closed
wants to merge 13 commits into from
Closed
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ inputs:
brillig_report_bytes:
description: States whether the Brillig report is done with bytecode sizes rather than opcodes.
default: false
memory_report:
description: States whether we want to generate a report of memory usage.
default: false
required: false
# sortCriteria:
# description: The list of criteria to order diff rows by in the report (name | min | avg | median | max | calls), separated by a comma. Must have the same length as sortOrders.
# required: false
Expand Down
86 changes: 75 additions & 11 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ const report = core.getInput("report");
const header = core.getInput("header");
const brillig_report = core.getInput("brillig_report");
const brillig_report_bytes = core.getInput("brillig_report_bytes");
const memory_report = core.getInput("memory_report");
const summaryQuantile = parseFloat(core.getInput("summaryQuantile"));
// const sortCriteria = core.getInput("sortCriteria").split(",");
// const sortOrders = core.getInput("sortOrders").split(",");
Expand All @@ -418,6 +419,7 @@ const localReportPath = (0, path_1.resolve)(report);
const { owner, repo } = github_1.context.repo;
const repository = owner + "/" + repo;
let referenceContent;
let compareContent;
let refCommitHash;
function run() {
var _a, e_1, _b, _c;
Expand All @@ -428,6 +430,8 @@ function run() {
try {
// Upload the gates report to be used as a reference in later runs.
yield uploadArtifact();
core.info(`Loading reports from "${localReportPath}"`);
compareContent = fs.readFileSync(localReportPath, "utf8");
}
catch (error) {
return core.setFailed(error.message);
Expand All @@ -437,6 +441,7 @@ function run() {
if (github_1.context.eventName === "pull_request") {
try {
core.startGroup(`Searching artifact "${baseReport}" on repository "${repository}", on branch "${baseBranch}"`);
let count = 100;
let artifactId = null;
try {
// Artifacts are returned in most recent first order.
Expand All @@ -448,7 +453,11 @@ function run() {
_e = false;
try {
const res = _c;
if (count == 0) {
break;
}
const artifact = res.data.find((artifact) => !artifact.expired && artifact.name === baseReport);
count = count - 1;
if (!artifact) {
yield new Promise((resolve) => setTimeout(resolve, 900)); // avoid reaching the API rate limit
continue;
Expand Down Expand Up @@ -481,7 +490,7 @@ function run() {
});
const zip = new adm_zip_1.default(Buffer.from(res.data));
for (const entry of zip.getEntries()) {
core.info(`Loading gas reports from "${entry.entryName}"`);
core.info(`Loading reports from "${entry.entryName}"`);
referenceContent = zip.readAsText(entry);
}
core.endGroup();
Expand All @@ -494,18 +503,24 @@ function run() {
}
}
try {
core.startGroup("Load gas reports");
core.info(`Loading gas reports from "${localReportPath}"`);
const compareContent = fs.readFileSync(localReportPath, "utf8");
referenceContent !== null && referenceContent !== void 0 ? referenceContent : (referenceContent = compareContent); // if no source gas reports were loaded, defaults to the current gas reports
core.info(`Mapping compared gas reports`);
core.startGroup("Load reports");
referenceContent !== null && referenceContent !== void 0 ? referenceContent : (referenceContent = compareContent); // if no source reports were loaded, defaults to the current reports
if (memory_report) {
core.info(`Format Memory markdown rows`);
const memoryContent = (0, report_1.memoryReports)(compareContent);
const referenceReports = (0, report_1.memoryReports)(referenceContent);
const markdown = (0, report_1.computeMemoryDiff)(referenceReports, memoryContent);
core.setOutput("markdown", markdown);
return;
}
core.info(`Mapping compared reports`);
const compareReports = (0, report_1.loadReports)(compareContent);
core.info(`Got ${compareReports.programs.length} compare programs`);
core.info(`Mapping reference gas reports`);
core.info(`Mapping reference reports`);
const referenceReports = (0, report_1.loadReports)(referenceContent);
core.info(`Got ${compareReports.programs.length} reference programs`);
core.endGroup();
core.startGroup("Compute gas diff");
core.startGroup("Compute diff");
const [diffCircuitRows, diffBrilligRows] = (0, report_1.computeProgramDiffs)(referenceReports.programs, compareReports.programs);
let numDiffs = diffCircuitRows.length;
let summaryRows;
Expand All @@ -519,8 +534,6 @@ function run() {
core.info(`Format ACIR markdown rows`);
[summaryRows, fullReportRows] = (0, program_1.formatCircuitRows)(diffCircuitRows, summaryQuantile);
}
core.info(`Format markdown of ${numDiffs} diffs`);
// const [summaryRows, fullReportRows] = formatCircuitRows(diffCircuitRows, summaryQuantile);
const markdown = (0, program_1.formatMarkdownDiff)(header, repository, github_1.context.sha, summaryRows, fullReportRows, !brillig_report, brillig_report_bytes == "true", refCommitHash, summaryQuantile);
core.info(`Format shell of ${numDiffs} diffs`);
let shell;
Expand Down Expand Up @@ -571,7 +584,7 @@ run();
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.computeContractDiffs = exports.computeProgramDiffs = exports.computedWorkspaceDiff = exports.loadReports = exports.variation = void 0;
exports.computeMemoryDiff = exports.formatMemoryReport = exports.computeContractDiffs = exports.computeProgramDiffs = exports.computedWorkspaceDiff = exports.memoryReports = exports.loadReports = exports.variation = void 0;
const variation = (current, previous) => {
const delta = current - previous;
return {
Expand All @@ -586,6 +599,10 @@ const loadReports = (content) => {
return JSON.parse(content);
};
exports.loadReports = loadReports;
const memoryReports = (content) => {
return JSON.parse(content).memory_reports;
};
exports.memoryReports = memoryReports;
const computedWorkspaceDiff = (sourceReport, compareReport) => {
const [diffCircuits, diffBrilligs] = (0, exports.computeProgramDiffs)(sourceReport.programs, compareReport.programs);
return {
Expand Down Expand Up @@ -700,6 +717,53 @@ const computeContractDiff = (sourceReport, compareReport) => {
functions: functionDiffs,
};
};
const formatMemoryReport = (memReports) => {
let markdown = "## Peak Memory Sample\n | Program | Peak Memory |\n | --- | --- |\n";
for (let i = 0; i < memReports.length; i++) {
markdown = markdown.concat(" | ", memReports[i].artifact_name, " | ", memReports[i].peak_memory, " |\n");
}
return markdown;
};
exports.formatMemoryReport = formatMemoryReport;
const computeMemoryDiff = (refReports, memReports) => {
let markdown = "";
const diff_percentage = [];
let diff_column = false;
if (refReports.length === memReports.length) {
for (let i = 0; i < refReports.length; i++) {
let diff_str = "N/A";
if (refReports[i].artifact_name === memReports[i].artifact_name) {
const compPeak = memReports[i].peak_memory;
const refPeak = refReports[i].peak_memory;
let diff = 0;
if (compPeak[compPeak.length - 1] == refPeak[refPeak.length - 1]) {
const compPeakValue = parseInt(compPeak.substring(0, compPeak.length - 1));
const refPeakValue = parseInt(refPeak.substring(0, refPeak.length - 1));
diff = Math.floor(((compPeakValue - refPeakValue) / refPeakValue) * 100);
}
else {
diff = 100;
}
if (diff != 0) {
diff_column = true;
}
diff_str = diff.toString() + "%";
}
diff_percentage.push(diff_str);
}
}
if (diff_column == true) {
markdown = "## Peak Memory Sample\n | Program | Peak Memory | % |\n | --- | --- | --- |\n";
for (let i = 0; i < memReports.length; i++) {
markdown = markdown.concat(" | ", memReports[i].artifact_name, " | ", memReports[i].peak_memory, " | ", diff_percentage[i], " |\n");
}
}
else {
markdown = (0, exports.formatMemoryReport)(memReports);
}
return markdown;
};
exports.computeMemoryDiff = computeMemoryDiff;


/***/ }),
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

38 changes: 25 additions & 13 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ import {
formatShellDiff,
formatShellDiffBrillig,
} from "./format/program";
import { loadReports, computeProgramDiffs } from "./report";
import { loadReports, computeProgramDiffs, memoryReports, computeMemoryDiff } from "./report";

const token = process.env.GITHUB_TOKEN || core.getInput("token");
const report = core.getInput("report");
const header = core.getInput("header");
const brillig_report = core.getInput("brillig_report");
const brillig_report_bytes = core.getInput("brillig_report_bytes");
const memory_report = core.getInput("memory_report");
const summaryQuantile = parseFloat(core.getInput("summaryQuantile"));
// const sortCriteria = core.getInput("sortCriteria").split(",");
// const sortOrders = core.getInput("sortOrders").split(",");
Expand All @@ -39,6 +40,7 @@ const { owner, repo } = context.repo;
const repository = owner + "/" + repo;

let referenceContent: string;
let compareContent: string;
let refCommitHash: string | undefined;

async function run() {
Expand All @@ -48,6 +50,8 @@ async function run() {
try {
// Upload the gates report to be used as a reference in later runs.
await uploadArtifact();
core.info(`Loading reports from "${localReportPath}"`);
compareContent = fs.readFileSync(localReportPath, "utf8");
} catch (error) {
return core.setFailed((error as Error).message);
}
Expand All @@ -59,17 +63,20 @@ async function run() {
core.startGroup(
`Searching artifact "${baseReport}" on repository "${repository}", on branch "${baseBranch}"`
);

let count = 100;
let artifactId: number | null = null;
// Artifacts are returned in most recent first order.
for await (const res of octokit.paginate.iterator(octokit.rest.actions.listArtifactsForRepo, {
owner,
repo,
})) {
if (count == 0) {
break;
}
const artifact = res.data.find(
(artifact) => !artifact.expired && artifact.name === baseReport
);

count = count - 1;
if (!artifact) {
await new Promise((resolve) => setTimeout(resolve, 900)); // avoid reaching the API rate limit

Expand Down Expand Up @@ -98,7 +105,7 @@ async function run() {

const zip = new Zip(Buffer.from(res.data as ArrayBuffer));
for (const entry of zip.getEntries()) {
core.info(`Loading gas reports from "${entry.entryName}"`);
core.info(`Loading reports from "${entry.entryName}"`);
referenceContent = zip.readAsText(entry);
}
core.endGroup();
Expand All @@ -109,21 +116,28 @@ async function run() {
}

try {
core.startGroup("Load gas reports");
core.info(`Loading gas reports from "${localReportPath}"`);
const compareContent = fs.readFileSync(localReportPath, "utf8");
referenceContent ??= compareContent; // if no source gas reports were loaded, defaults to the current gas reports
core.startGroup("Load reports");
referenceContent ??= compareContent; // if no source reports were loaded, defaults to the current reports

if (memory_report) {
core.info(`Format Memory markdown rows`);
const memoryContent = memoryReports(compareContent);
const referenceReports = memoryReports(referenceContent);
const markdown = computeMemoryDiff(referenceReports, memoryContent);
core.setOutput("markdown", markdown);
return;
}

core.info(`Mapping compared gas reports`);
core.info(`Mapping compared reports`);
const compareReports = loadReports(compareContent);
core.info(`Got ${compareReports.programs.length} compare programs`);

core.info(`Mapping reference gas reports`);
core.info(`Mapping reference reports`);
const referenceReports = loadReports(referenceContent);
core.info(`Got ${compareReports.programs.length} reference programs`);
core.endGroup();

core.startGroup("Compute gas diff");
core.startGroup("Compute diff");
const [diffCircuitRows, diffBrilligRows] = computeProgramDiffs(
referenceReports.programs,
compareReports.programs
Expand All @@ -141,8 +155,6 @@ async function run() {
[summaryRows, fullReportRows] = formatCircuitRows(diffCircuitRows, summaryQuantile);
}

core.info(`Format markdown of ${numDiffs} diffs`);
// const [summaryRows, fullReportRows] = formatCircuitRows(diffCircuitRows, summaryQuantile);
const markdown = formatMarkdownDiff(
header,
repository,
Expand Down
69 changes: 69 additions & 0 deletions src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ProgramReport,
BrilligReport,
DiffBrillig,
MemoryReport,
} from "./types";

export const variation = (current: number, previous: number) => {
Expand All @@ -27,6 +28,10 @@ export const loadReports = (content: string): WorkspaceReport => {
return JSON.parse(content);
};

export const memoryReports = (content: string): MemoryReport[] => {
return JSON.parse(content).memory_reports;
};

export const computedWorkspaceDiff = (
sourceReport: WorkspaceReport,
compareReport: WorkspaceReport
Expand Down Expand Up @@ -193,3 +198,67 @@ const computeContractDiff = (
functions: functionDiffs,
};
};

export const formatMemoryReport = (memReports: MemoryReport[]): string => {
let markdown = "## Peak Memory Sample\n | Program | Peak Memory |\n | --- | --- |\n";
for (let i = 0; i < memReports.length; i++) {
markdown = markdown.concat(
" | ",
memReports[i].artifact_name,
" | ",
memReports[i].peak_memory,
" |\n"
);
}
return markdown;
};

export const computeMemoryDiff = (
refReports: MemoryReport[],
memReports: MemoryReport[]
): string => {
let markdown = "";
const diff_percentage = [];
let diff_column = false;
if (refReports.length === memReports.length) {
for (let i = 0; i < refReports.length; i++) {
let diff_str = "N/A";
if (refReports[i].artifact_name === memReports[i].artifact_name) {
const compPeak = memReports[i].peak_memory;
const refPeak = refReports[i].peak_memory;
let diff = 0;
if (compPeak[compPeak.length - 1] == refPeak[refPeak.length - 1]) {
const compPeakValue = parseInt(compPeak.substring(0, compPeak.length - 1));
const refPeakValue = parseInt(refPeak.substring(0, refPeak.length - 1));
diff = Math.floor(((compPeakValue - refPeakValue) / refPeakValue) * 100);
} else {
diff = 100;
}
if (diff != 0) {
diff_column = true;
}
diff_str = diff.toString() + "%";
}
diff_percentage.push(diff_str);
}
}

if (diff_column == true) {
markdown = "## Peak Memory Sample\n | Program | Peak Memory | % |\n | --- | --- | --- |\n";
for (let i = 0; i < memReports.length; i++) {
markdown = markdown.concat(
" | ",
memReports[i].artifact_name,
" | ",
memReports[i].peak_memory,
" | ",
diff_percentage[i],
" |\n"
);
}
} else {
markdown = formatMemoryReport(memReports);
}

return markdown;
};
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ export interface DiffCell {
percentage: number;
}

export interface MemoryReport {
artifact_name: string;
peak_memory: string;
}

export interface MemoryReports {
memory_reports: MemoryReport[];
}

export type SortCriterion = keyof DiffCircuit;
export type SortOrder = "asc" | "desc";

Expand Down
Loading