A lightweight stopwatch, benchmark reporting, and baseline comparison toolkit for MoonBit projects.
moon add Han-Wentao/moonbenchhttps://mooncakes.io/docs/Han-Wentao/moonbenchlet stats = @moonbench.SampleStats::from_samples([10.0, 4.0, 8.0, 6.0])
println(stats.mean_us)
println(stats.median_us)let watch = @moonbench.Stopwatch::new().start(100).stop(160).start(200)
println(watch.elapsed(250))let result = @moonbench.BenchmarkRunner::new(warmup=0, iterations=3).run(
"manual-sample",
() => 42.0,
)
println(result.to_markdown())let mut value = 0
let result = @moonbench.BenchmarkRunner::new(warmup=1, iterations=4).run_timed(
"increment",
() => {
value = value + 1
ignore(value)
},
)
println(result.to_json_with_samples())let runner = @moonbench.BenchmarkRunner::new(warmup=1, iterations=4)
let mut current = 0
let increment = runner.run_timed("increment-example", () => {
current = current + 1
ignore(current)
})
let arithmetic = runner.run("manual-sample-example", () => 42.0)
let suite = @moonbench.BenchmarkSuite::new(
title="Basic MoonBench example",
package_name="Han-Wentao/moonbench",
package_version="0.3.0",
target="wasm-gc",
).add(increment).add(arithmetic)
println(suite.to_markdown())
println(suite.to_csv())
println(suite.to_json())let report = @moonbench.BaselineSet::new()
.add("increment-example", increment.stats.mean_us)
.add("manual-sample-example", 40.0)
.compare_suite(suite, tolerance_pct=5.0)
println(report.to_markdown())
println(report.to_json())let parsed = @moonbench.BaselineSet::parse_text(
"# moonbench.baseline\nparse=12.5\nrender=40.0\n",
)
if parsed.is_valid() {
println(parsed.baselines.compare_suite(suite).to_markdown())
} else {
println(parsed.issues_to_markdown())
}let metadata = @moonbench.ReportMetadata::new(
title="MoonBench CI Report",
package_name="Han-Wentao/moonbench",
package_version="0.3.0",
target="wasm-gc",
note="Generated in CI",
)
println(metadata.to_markdown())let issue = @moonbench.validate_benchmark_name("case-1")
println(issue.ok)
println(@moonbench.normalize_benchmark_name("a|b\nc"))result.to_markdown()
result.to_json()
result.to_json_with_samples()
result.to_csv_row()suite.to_markdown()
suite.to_json()
suite.to_csv()comparison_report.to_markdown()
comparison_report.to_json()moon check
moon test
moon run cmd/main
moon run examples/basic
moon packagepub(all) struct BaselineParseReport {
baselines : BaselineSet
issues : Array[BaselineParseIssue]
} derive(Eq, Debug)fn BaselineSet::compare_suite(self : BaselineSet, suite : BenchmarkSuite, tolerance_pct? : Double) -> ComparisonReportpub(all) struct BenchmarkResult {
name : String
warmup : Int
iterations : Int
samples_us : Array[Double]
stats : SampleStats
} derive(Eq, Debug)fn BenchmarkResult::compare_baseline(self : BenchmarkResult, baseline_mean_us : Double, tolerance_pct? : Double) -> BaselineComparisonfn BenchmarkRunner::run(self : BenchmarkRunner, name : String, measure : () -> Double) -> BenchmarkResultfn BenchmarkRunner::run_timed(self : BenchmarkRunner, name : String, body : () -> Unit) -> BenchmarkResultpub(all) struct BenchmarkSnapshot {
label : String
commit : String
target : String
created_at : String
metrics : Array[MetricSnapshot]
} derive(Eq, Debug)fn BenchmarkSnapshot::diff(self : BenchmarkSnapshot, after : BenchmarkSnapshot, tolerance_pct? : Double) -> SnapshotDiffReportfn BenchmarkSnapshot::from_suite(suite : BenchmarkSuite, label? : String, commit? : String, target? : String, created_at? : String) -> BenchmarkSnapshotfn BenchmarkSnapshot::new(label? : String, commit? : String, target? : String, created_at? : String) -> BenchmarkSnapshotpub(all) struct BenchmarkSuite {
metadata : ReportMetadata
results : Array[BenchmarkResult]
} derive(Eq, Debug)fn BenchmarkSuite::new(title? : String, package_name? : String, package_version? : String, target? : String, note? : String) -> BenchmarkSuitefn ChecklistItem::new(id : String, title : String, description? : String, done? : Bool, evidence? : String, required? : Bool) -> ChecklistItempub(all) struct ComparisonReport {
comparisons : Array[NamedComparison]
summary : TrendSummary
} derive(Eq, Debug)fn DocTemplate::new(id : String, title : String, audience? : String, purpose? : String, body? : String, required? : Bool) -> DocTemplatefn GateDecision::new(name : String, passed : Bool, status : String, reason : String, severity? : String, delta_pct? : Double, sample_count? : Int, cv_pct? : Double) -> GateDecisionpub(all) struct GateReport {
policy : ThresholdPolicy
decisions : Array[GateDecision]
} derive(Eq, Debug)fn GateReport::from_comparison_report(report : ComparisonReport, policy? : ThresholdPolicy) -> GateReportpub(all) struct GitHubStepSummary {
title : String
badges : BadgeSet
reviewer_summary : ReviewerSummary
suite : BenchmarkSuite
gate : GateReport
} derive(Eq, Debug)fn GitHubStepSummary::new(title? : String, badges? : BadgeSet, reviewer_summary? : ReviewerSummary, suite? : BenchmarkSuite, gate? : GateReport) -> GitHubStepSummarypub(all) struct MarkdownDocument {
title : String
intro : String
sections : Array[MarkdownSection]
} derive(Eq, Debug)fn MarkdownDocument::add_section(self : MarkdownDocument, section : MarkdownSection) -> MarkdownDocumentfn MarkdownDocument::section(self : MarkdownDocument, title : String, body : String, level? : Int) -> MarkdownDocumentfn MarkdownDocument::with_artifacts(self : MarkdownDocument, bundle : ArtifactBundle, title? : String) -> MarkdownDocumentfn MarkdownDocument::with_comparison(self : MarkdownDocument, report : ComparisonReport, title? : String) -> MarkdownDocumentfn MarkdownDocument::with_gate(self : MarkdownDocument, gate : GateReport, title? : String) -> MarkdownDocumentfn MarkdownDocument::with_suite(self : MarkdownDocument, suite : BenchmarkSuite, title? : String) -> MarkdownDocumentfn MetricSnapshot::new(name : String, mean_us : Double, median_us? : Double, p90_us? : Double, p95_us? : Double, stddev_us? : Double, samples? : Int) -> MetricSnapshotpub(all) struct ProjectScorecard {
title : String
target_loc : Int
actual_loc : Int
sections : Array[ScoreSection]
} derive(Eq, Debug)fn ProjectScorecard::add_section(self : ProjectScorecard, section : ScoreSection) -> ProjectScorecardfn ReleaseNoteEntry::new(kind : String, title : String, detail? : String, issue? : String) -> ReleaseNoteEntrypub(all) struct ReleaseNotes {
version : String
date : String
entries : Array[ReleaseNoteEntry]
} derive(Eq, Debug)fn ReportMetadata::new(title? : String, package_name? : String, package_version? : String, target? : String, note? : String) -> ReportMetadatafn ReviewerSummary::new(project? : String, package_name? : String, version? : String, github_url? : String, package_url? : String) -> ReviewerSummaryfn SampleSeries::analyze(self : SampleSeries, tolerance_pct? : Double, noisy_cv_pct? : Double) -> TrendAnalysispub(all) struct ScenarioCatalog {
title : String
scenarios : Array[WorkloadScenario]
} derive(Eq, Debug)fn ScenarioCatalog::filter_priority(self : ScenarioCatalog, minimum_priority : Int) -> ScenarioCatalogfn SnapshotDiff::new(name : String, before_found : Bool, after_found : Bool, before_mean_us : Double, after_mean_us : Double, tolerance_pct? : Double) -> SnapshotDiffpub(all) struct SnapshotDiffReport {
before_label : String
after_label : String
diffs : Array[SnapshotDiff]
} derive(Eq, Debug)fn SnapshotDiffReport::to_gate_report(self : SnapshotDiffReport, policy? : ThresholdPolicy) -> GateReportfn StatusBadge::new(label : String, message : String, color? : String, link? : String) -> StatusBadgepub(all) struct SubmissionChecklist {
title : String
items : Array[ChecklistItem]
} derive(Eq, Debug)fn SubmissionChecklist::add(self : SubmissionChecklist, item : ChecklistItem) -> SubmissionChecklistfn ThresholdPolicy::new(name? : String, faster_pct? : Double, slower_pct? : Double, noisy_cv_pct? : Double, minimum_samples? : Int, allow_missing_baseline? : Bool) -> ThresholdPolicypub(all) struct TrendAnalysis {
name : String
unit : String
count : Int
first : Double
latest : Double
min : Double
max : Double
mean : Double
median : Double
p90 : Double
p95 : Double
stddev : Double
latest_delta_pct : Double
coefficient_of_variation_pct : Double
stable_ratio : Double
outlier_count : Int
direction : String
risk : String
} derive(Eq, Debug)fn WorkloadScenario::new(id : String, name : String, category? : String, description? : String, tags? : Array[String], data_size? : Int, warmup? : Int, iterations? : Int, expected_unit? : String, complexity? : String, priority? : Int) -> WorkloadScenariofn normalize_benchmark_name(name : String) -> StringA lightweight stopwatch, benchmark reporting, and baseline comparison toolkit for MoonBit projects.