Repository: dfinity/new-motoko-base
Pull request #234: Add Benchmarks
Author: login: Kamirus
Created: 2025-03-20T09:32:51Z | Merged: 2025-03-25T08:33:42Z

This pull request introduces benchmarking setup to the new base library:
- Uses [`mops bench`](https://docs.mops.one/cli/mops-bench) to run benchmarks
- Benchmarks are defined using the [`bench` package](https://mops.one/bench)
- Defines the first benchmark in `bench/`
- Sets up the github workflow that:
  - Creates/Updates a comment with the benchmark results compared to the `main` branch. (see the comment below)
  - Updates the benchmark results ([current baseline here](https://github.com/dfinity/new-motoko-base/tree/benchmark-results)) after each push to `main`


Diff:
diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml
new file mode 100644
index 000000000..90e19d4cf
--- /dev/null
+++ b/.github/workflows/benchmarks.yml
@@ -0,0 +1,90 @@
+name: Benchmarks
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+
+jobs:
+  benchmark:
+    runs-on: ubuntu-24.04
+    name: Run Benchmarks and Comment on PR or Upload on push
+
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: actions/setup-node@v4
+        with:
+          cache: 'npm'
+      - name: Cache mops packages
+        uses: actions/cache@v4
+        with:
+          key: mops-packages-${{ hashFiles('mops.toml') }}
+          restore-keys: |
+            mops-packages-${{ hashFiles('mops.toml') }}
+            mops-packages-
+          path: |
+            ~/.cache/mops
+      - run: npm ci
+      - run: npx mops toolchain init
+      - name: Install dfx
+        uses: dfinity/setup-dfx@main
+      - name: Install dfx cache
+        run: dfx cache install
+
+      - name: Checkout out the branch with benchmark results
+        if: github.event_name == 'pull_request'
+        uses: actions/checkout@v4
+        with:
+          ref: benchmark-results
+          path: .benchmark-results-branch/
+      - name: Move Saved Benchmarks
+        if: github.event_name == 'pull_request'
+        run: mv .benchmark-results-branch/.bench .bench
+      - name: Benchmarks Table
+        if: github.event_name == 'pull_request'
+        id: benchmarks
+        run: |  # Make sure to use the same flags as in the `mops bench` command below!
+          npx mops bench --compare 2>&1 | tee benchmark_results.txt
+          echo "result<<EOF" >> $GITHUB_OUTPUT
+          cat benchmark_results.txt >> $GITHUB_OUTPUT
+          echo "EOF" >> $GITHUB_OUTPUT
+      - name: Find Comment
+        if: github.event_name == 'pull_request'
+        uses: peter-evans/find-comment@v3
+        id: fc
+        with:
+          issue-number: ${{ github.event.pull_request.number }}
+          comment-author: 'github-actions[bot]'
+          body-includes: Benchmark Results
+      - name: Create or update comment
+        if: github.event_name == 'pull_request'
+        uses: peter-evans/create-or-update-comment@v4
+        with:
+          comment-id: ${{ steps.fc.outputs.comment-id }}
+          issue-number: ${{ github.event.pull_request.number }}
+          body: |
+            ${{ steps.benchmarks.outputs.result }}
+            **Note**: Renamed benchmarks cannot be compared. Refer to the [current baseline](https://github.com/dfinity/new-motoko-base/tree/benchmark-results) for manual comparison.
+          edit-mode: replace
+
+      - name: Generate Benchmark Results
+        if: github.event_name != 'pull_request'
+        run: | # Make sure to use the same flags as in the `mops bench` command above!
+          npx mops bench --save 2>&1 | tee bench-results.md 
+      - name: Move Generated Results
+        if: github.event_name != 'pull_request'
+        run: |
+          mkdir .bench-br
+          mv .bench .bench-br/.bench
+          mv bench-results.md .bench-br/README.md
+      - name: Upload benchmark results
+        if: github.event_name != 'pull_request'
+        uses: JamesIves/github-pages-deploy-action@v4
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          branch: benchmark-results
+          folder: .bench-br
diff --git a/bench/FromIters.bench.mo b/bench/FromIters.bench.mo
new file mode 100644
index 000000000..3e6e17430
--- /dev/null
+++ b/bench/FromIters.bench.mo
@@ -0,0 +1,52 @@
+import Bench "mo:bench";
+import Fuzz "mo:fuzz";
+
+import Array "../src/Array";
+import List "../src/pure/List";
+import Runtime "../src/Runtime";
+import Nat "../src/Nat";
+
+module {
+  public func init() : Bench.Bench {
+    let bench = Bench.Bench();
+
+    bench.name("Benchmarking the fromIter functions");
+    bench.description("Columns describe the number of elements in the input iter.");
+
+    bench.rows([
+      "Array.fromIter",
+      "List.fromIter"
+    ]);
+    bench.cols([
+      "100",
+      "10_000",
+      "100_000"
+    ]);
+
+    let fuzz = Fuzz.fromSeed(27850937); // fix seed for reproducibility
+
+    func input(n : Nat) : [Nat] = fuzz.array.randomArray(n, fuzz.nat.random);
+
+    let array1 = input(100);
+    let array2 = input(10_000);
+    let array3 = input(100_000);
+
+    bench.runner(
+      func(row, col) {
+        let array = switch col {
+          case "100" array1;
+          case "10_000" array2;
+          case "100_000" array3;
+          case _ Runtime.unreachable()
+        };
+        switch (row) {
+          case "List.fromIter" ignore List.fromIter(array.vals());
+          case "Array.fromIter" ignore Array.fromIter(array.vals());
+          case _ return ()
+        }
+      }
+    );
+
+    bench
+  }
+}
diff --git a/mops.toml b/mops.toml
index 345c8d136..1f411ef94 100644
--- a/mops.toml
+++ b/mops.toml
@@ -7,8 +7,10 @@ keywords = [ "base" ]
 license = "Apache-2.0"
 
 [dev-dependencies]
-matchers = "https://github.com/kritzcreek/motoko-matchers#v1.3.1@5ba5f52bd9a5649dedf5e2a1ccd55d98ed7ff982"
 test = "2.1.0"
+bench = "1.0.0"
+fuzz = "0.2.1"
+matchers = "https://github.com/kritzcreek/motoko-matchers#v1.3.1@5ba5f52bd9a5649dedf5e2a1ccd55d98ed7ff982"
 
 [toolchain]
 moc = "0.13.7"
diff --git a/package-lock.json b/package-lock.json
index d44206a85..5858ec9e0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
       "devDependencies": {
         "execa": "^4.1.0",
         "fast-glob": "^3.3.2",
-        "ic-mops": "^1.1.1",
+        "ic-mops": "^1.4.0",
         "mo-dev": "^0.13.0",
         "npm-run-all": "^4.1.5",
         "prettier": "2",
@@ -21,9 +21,9 @@
       }
     },
     "node_modules/@dfinity/agent": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-2.1.0.tgz",
-      "integrity": "sha512-DXIg9Yx/80xERtEXzd37jGA/5kyR4gC57A3+JElOvBt/lWlfq+cEemaAEArI+cYmeE0xkB9DROCM7r5yEbRg7Q==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-2.3.0.tgz",
+      "integrity": "sha512-f/eNydwuOunTKRcZAW1RxrcmKyb1AFqZM/ysJJaqFCX9Y+men9NoBTeuUI23XKUp9YeDb9yinGyAlYqjb6VMPw==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -35,8 +35,8 @@
         "simple-cbor": "^0.4.1"
       },
       "peerDependencies": {
-        "@dfinity/candid": "^2.1.0",
-        "@dfinity/principal": "^2.1.0"
+        "@dfinity/candid": "^2.3.0",
+        "@dfinity/principal": "^2.3.0"
       }
     },
     "node_modules/@dfinity/agent/node_modules/buffer": {
@@ -65,19 +65,19 @@
       }
     },
     "node_modules/@dfinity/candid": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-2.1.0.tgz",
-      "integrity": "sha512-MMD+bcIVrIJTLjyGx8xpj8A0Dwb8OPrFXWp/QHGXTSOezXxSMp2yG2QjxYkbV4EN5eCkwjeOY5mH2gHSa18pNA==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@dfinity/candid/-/candid-2.3.0.tgz",
+      "integrity": "sha512-Xzj3EWfwaVZy90jq6WBRP4Cyqo93r3g8tvBea8W8PN3I4W6KcN2/9ZJaBhT3Y4NP+p2w4ZO6aJ+qp9xH990aYw==",
       "dev": true,
       "license": "Apache-2.0",
       "peerDependencies": {
-        "@dfinity/principal": "^2.1.0"
+        "@dfinity/principal": "^2.3.0"
       }
     },
     "node_modules/@dfinity/identity": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-2.1.0.tgz",
-      "integrity": "sha512-cB16Af65RpJwc3JR4r0jV+TckDiflPFHSRUh/JZ3920CUEDB1wYbzCcUtUb/IWiU101oKZNi5QdQrHp1haZq6w==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@dfinity/identity/-/identity-2.3.0.tgz",
+      "integrity": "sha512-nJbL9hNztfhjmdkSmzoUi/cuLmCtjm9/8O6dM100acMjqG1JoW4yF4Mgi/sKwCDCkpj+maY8SqQxI8hSPms9gA==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -86,19 +86,18 @@
         "borc": "^2.1.1"
       },
       "peerDependencies": {
-        "@dfinity/agent": "^2.1.0",
-        "@dfinity/principal": "^2.1.0",
-        "@peculiar/webcrypto": "^1.4.0"
+        "@dfinity/agent": "^2.3.0",
+        "@dfinity/principal": "^2.3.0"
       }
     },
     "node_modules/@dfinity/identity-secp256k1": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@dfinity/identity-secp256k1/-/identity-secp256k1-2.1.0.tgz",
-      "integrity": "sha512-F5aoWfTJAZrXbxI8BaSnKOe4DF0R5GnWXRrecj5M6+KHh2e/OMRsJwyJ4cn5yQHUf3pUvowFFwldcZmbc1vEOg==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@dfinity/identity-secp256k1/-/identity-secp256k1-2.3.0.tgz",
+      "integrity": "sha512-rU1/xz5uy5iqAR55X4Qs11VeWY2hngIWlo9yJhxdgyI0V0Ri6aHDh1ONE4ate8CbDotRER9KLMLWObcCvfUp5g==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
-        "@dfinity/agent": "^2.1.0",
+        "@dfinity/agent": "^2.3.0",
         "@noble/curves": "^1.4.0",
         "@noble/hashes": "^1.3.1",
         "@scure/bip32": "^1.4.0",
@@ -108,9 +107,9 @@
       }
     },
     "node_modules/@dfinity/principal": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-2.1.0.tgz",
-      "integrity": "sha512-nC3tI2Kxe9153mI3QdWzAsCnsyNygqnb9O/qhJOks97RCE1vfn3nkhq4dN6yBVpvlCv3hOMSleAcZm3DzH3NsQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@dfinity/principal/-/principal-2.3.0.tgz",
+      "integrity": "sha512-rb3TsxR3L/Vq2GWV/GGIMXPbzDDqxNohPbNW8nJKhpcm8Ds00tCVEmPUDqrn735xJW0Pmzog/6/S1L9jG2UT9g==",
       "dev": true,
       "license": "Apache-2.0",
       "dependencies": {
@@ -975,13 +974,13 @@
       }
     },
     "node_modules/@noble/curves": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz",
-      "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==",
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz",
+      "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@noble/hashes": "1.6.0"
+        "@noble/hashes": "1.7.1"
       },
       "engines": {
         "node": "^14.21.3 || >=16"
@@ -990,23 +989,10 @@
         "url": "https://paulmillr.com/funding/"
       }
     },
-    "node_modules/@noble/curves/node_modules/@noble/hashes": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz",
-      "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "^14.21.3 || >=16"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
     "node_modules/@noble/hashes": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz",
-      "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==",
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz",
+      "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1597,51 +1583,6 @@
       "dev": true,
       "license": "MIT"
     },
-    "node_modules/@peculiar/asn1-schema": {
-      "version": "2.3.13",
-      "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.13.tgz",
-      "integrity": "sha512-3Xq3a01WkHRZL8X04Zsfg//mGaA21xlL4tlVn4v2xGT0JStiztATRkMwa5b+f/HXmY2smsiLXYK46Gwgzvfg3g==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "asn1js": "^3.0.5",
-        "pvtsutils": "^1.3.5",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@peculiar/json-schema": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz",
-      "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "tslib": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/@peculiar/webcrypto": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz",
-      "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "@peculiar/asn1-schema": "^2.3.8",
-        "@peculiar/json-schema": "^1.1.12",
-        "pvtsutils": "^1.3.5",
-        "tslib": "^2.6.2",
-        "webcrypto-core": "^1.8.0"
-      },
-      "engines": {
-        "node": ">=10.12.0"
-      }
-    },
     "node_modules/@pkgjs/parseargs": {
       "version": "0.11.0",
       "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -1654,9 +1595,9 @@
       }
     },
     "node_modules/@scure/base": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz",
-      "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==",
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.4.tgz",
+      "integrity": "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==",
       "dev": true,
       "license": "MIT",
       "funding": {
@@ -1664,55 +1605,29 @@
       }
     },
     "node_modules/@scure/bip32": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.0.tgz",
-      "integrity": "sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==",
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz",
+      "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@noble/curves": "~1.7.0",
-        "@noble/hashes": "~1.6.0",
-        "@scure/base": "~1.2.1"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/@scure/bip32/node_modules/@noble/hashes": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz",
-      "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "^14.21.3 || >=16"
+        "@noble/curves": "~1.8.1",
+        "@noble/hashes": "~1.7.1",
+        "@scure/base": "~1.2.2"
       },
       "funding": {
         "url": "https://paulmillr.com/funding/"
       }
     },
     "node_modules/@scure/bip39": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.0.tgz",
-      "integrity": "sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==",
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz",
+      "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@noble/hashes": "~1.6.0",
-        "@scure/base": "~1.2.1"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/@scure/bip39/node_modules/@noble/hashes": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz",
-      "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "^14.21.3 || >=16"
+        "@noble/hashes": "~1.7.1",
+        "@scure/base": "~1.2.4"
       },
       "funding": {
         "url": "https://paulmillr.com/funding/"
@@ -1827,9 +1742,9 @@
       }
     },
     "node_modules/@types/ms": {
-      "version": "0.7.34",
-      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz",
-      "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+      "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
       "dev": true,
       "license": "MIT"
     },
@@ -2051,9 +1966,9 @@
       "optional": true
     },
     "node_modules/base-x": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
-      "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz",
+      "integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==",
       "dev": true,
       "license": "MIT"
     },
@@ -2503,23 +2418,10 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/camelcase": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
-      "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/chalk": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
-      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
+      "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2529,6 +2431,13 @@
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "node_modules/change-case": {
+      "version": "5.4.4",
+      "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz",
+      "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/character-entities": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
@@ -2629,9 +2538,9 @@
       "license": "MIT"
     },
     "node_modules/commander": {
-      "version": "12.1.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
-      "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+      "version": "13.1.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
+      "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -2862,9 +2771,9 @@
       }
     },
     "node_modules/decode-named-character-reference": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
-      "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz",
+      "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -4179,9 +4088,9 @@
       }
     },
     "node_modules/glob": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
-      "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+      "version": "11.0.1",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
+      "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
       "dev": true,
       "license": "ISC",
       "dependencies": {
@@ -4266,13 +4175,13 @@
       }
     },
     "node_modules/got": {
-      "version": "14.4.2",
-      "resolved": "https://registry.npmjs.org/got/-/got-14.4.2.tgz",
-      "integrity": "sha512-+Te/qEZ6hr7i+f0FNgXx/6WQteSM/QqueGvxeYQQFm0GDfoxLVJ/oiwUKYMTeioColWUTdewZ06hmrBjw6F7tw==",
+      "version": "14.4.6",
+      "resolved": "https://registry.npmjs.org/got/-/got-14.4.6.tgz",
+      "integrity": "sha512-rnhwfM/PhMNJ1i17k3DuDqgj0cKx3IHxBKVv/WX1uDKqrhi2Gv3l7rhPThR/Cc6uU++dD97W9c8Y0qyw9x0jag==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@sindresorhus/is": "^7.0.0",
+        "@sindresorhus/is": "^7.0.1",
         "@szmarczak/http-timer": "^5.0.1",
         "cacheable-lookup": "^7.0.0",
         "cacheable-request": "^12.0.1",
@@ -4282,7 +4191,7 @@
         "lowercase-keys": "^3.0.0",
         "p-cancelable": "^4.0.1",
         "responselike": "^3.0.0",
-        "type-fest": "^4.19.0"
+        "type-fest": "^4.26.1"
       },
       "engines": {
         "node": ">=20"
@@ -4448,26 +4357,26 @@
       }
     },
     "node_modules/ic-mops": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ic-mops/-/ic-mops-1.1.1.tgz",
-      "integrity": "sha512-1w0MYPiz2fi6gyvfJZaWPHG4WKpMAD+ggHZtcyd9kfIDLR7S+kgi7E00lXWhTvBAgRpuozzdyN+tP5CL3pxyXQ==",
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/ic-mops/-/ic-mops-1.4.0.tgz",
+      "integrity": "sha512-EPuhzUVFFMBcZcbrFkiA27GXWUDTNo5ptoWKdM0oWXKl9TqfAGQ44ZpSTdYG7kagomW4j+zpGz2xhsMuDLMI6Q==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@dfinity/agent": "2.1.0",
-        "@dfinity/candid": "2.1.0",
-        "@dfinity/identity": "2.1.0",
-        "@dfinity/identity-secp256k1": "2.1.0",
-        "@dfinity/principal": "2.1.0",
+        "@dfinity/agent": "2.3.0",
+        "@dfinity/candid": "2.3.0",
+        "@dfinity/identity": "2.3.0",
+        "@dfinity/identity-secp256k1": "2.3.0",
+        "@dfinity/principal": "2.3.0",
         "@iarna/toml": "2.2.5",
-        "@noble/hashes": "1.5.0",
+        "@noble/hashes": "1.7.1",
         "as-table": "1.0.55",
         "buffer": "6.0.3",
         "cacheable-request": "12.0.1",
-        "camelcase": "8.0.0",
-        "chalk": "5.3.0",
+        "chalk": "5.4.1",
+        "change-case": "5.4.4",
         "chokidar": "3.6.0",
-        "commander": "12.1.0",
+        "commander": "13.1.0",
         "debounce": "2.1.1",
         "decomp-tarxz": "0.1.1",
         "decompress": "4.2.1",
@@ -4477,13 +4386,13 @@
         "filesize": "10.1.6",
         "fs-extra": "11.2.0",
         "get-folder-size": "5.0.0",
-        "glob": "11.0.0",
+        "glob": "11.0.1",
         "globby": "14.0.2",
-        "got": "14.4.2",
+        "got": "14.4.6",
         "log-update": "6.1.0",
-        "markdown-table": "3.0.3",
-        "mdast-util-from-markdown": "2.0.1",
-        "mdast-util-to-markdown": "2.1.0",
+        "markdown-table": "3.0.4",
+        "mdast-util-from-markdown": "2.0.2",
+        "mdast-util-to-markdown": "2.1.2",
         "minimatch": "10.0.1",
         "ncp": "2.0.0",
         "node-fetch": "3.3.2",
@@ -4492,10 +4401,11 @@
         "pic-ic": "0.5.3",
         "promisify-child-process": "4.1.2",
         "prompts": "2.4.2",
-        "semver": "7.6.3",
+        "semver": "7.7.1",
         "stream-to-promise": "3.0.0",
         "string-width": "7.2.0",
-        "tar": "7.4.3"
+        "tar": "7.4.3",
+        "terminal-size": "4.0.0"
       },
       "bin": {
         "ic-mops": "dist/bin/mops.js",
@@ -5321,9 +5231,9 @@
       }
     },
     "node_modules/jackspeak": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
-      "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz",
+      "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==",
       "dev": true,
       "license": "BlueOak-1.0.0",
       "dependencies": {
@@ -5611,9 +5521,9 @@
       }
     },
     "node_modules/markdown-table": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
-      "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+      "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
       "dev": true,
       "license": "MIT",
       "funding": {
@@ -5632,9 +5542,9 @@
       }
     },
     "node_modules/mdast-util-from-markdown": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz",
-      "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
+      "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -5672,9 +5582,9 @@
       }
     },
     "node_modules/mdast-util-to-markdown": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz",
-      "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+      "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -5683,6 +5593,7 @@
         "longest-streak": "^3.0.0",
         "mdast-util-phrasing": "^4.0.0",
         "mdast-util-to-string": "^4.0.0",
+        "micromark-util-classify-character": "^2.0.0",
         "micromark-util-decode-string": "^2.0.0",
         "unist-util-visit": "^5.0.0",
         "zwitch": "^2.0.0"
@@ -5763,9 +5674,9 @@
       }
     },
     "node_modules/micromark": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz",
-      "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+      "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
       "dev": true,
       "funding": [
         {
@@ -5799,9 +5710,9 @@
       }
     },
     "node_modules/micromark-core-commonmark": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz",
-      "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+      "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
       "dev": true,
       "funding": [
         {
@@ -6169,9 +6080,9 @@
       }
     },
     "node_modules/micromark-util-subtokenize": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz",
-      "integrity": "sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+      "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
       "dev": true,
       "funding": [
         {
@@ -6209,9 +6120,9 @@
       "license": "MIT"
     },
     "node_modules/micromark-util-types": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz",
-      "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+      "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
       "dev": true,
       "funding": [
         {
@@ -8131,9 +8042,9 @@
       "license": "MIT"
     },
     "node_modules/semver": {
-      "version": "7.6.3",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
-      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+      "version": "7.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+      "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
       "dev": true,
       "license": "ISC",
       "bin": {
@@ -8811,6 +8722,19 @@
         "streamx": "^2.15.0"
       }
     },
+    "node_modules/terminal-size": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/terminal-size/-/terminal-size-4.0.0.tgz",
+      "integrity": "sha512-rcdty1xZ2/BkWa4ANjWRp4JGpda2quksXIHgn5TMjNBPZfwzJIgR68DKfSYiTL+CZWowDX/sbOo5ME/FRURvYQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/text-decoder": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz",
@@ -8900,9 +8824,9 @@
       }
     },
     "node_modules/type-fest": {
-      "version": "4.28.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.28.1.tgz",
-      "integrity": "sha512-LO/+yb3mf46YqfUC7QkkoAlpa7CTYh//V1Xy9+NQ+pKqDqXIq0NTfPfQRwFfCt+if4Qkwb9gzZfsl6E5TkXZGw==",
+      "version": "4.38.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz",
+      "integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==",
       "dev": true,
       "license": "(MIT OR CC0-1.0)",
       "engines": {
@@ -9206,21 +9130,6 @@
         "node": ">= 8"
       }
     },
-    "node_modules/webcrypto-core": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz",
-      "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "@peculiar/asn1-schema": "^2.3.13",
-        "@peculiar/json-schema": "^1.1.12",
-        "asn1js": "^3.0.5",
-        "pvtsutils": "^1.3.5",
-        "tslib": "^2.7.0"
-      }
-    },
     "node_modules/webidl-conversions": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
diff --git a/package.json b/package.json
index 4509ec16c..8c8c27b24 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
     "validate:changelog": "cd test/ts/validate && tsx changelog",
     "validate:version": "cd test/ts/validate && tsx version",
     "validate:api": "cd test/ts/validate && tsx api",
-    "docs": "$(dfx cache show)/mo-doc"
+    "docs": "$(dfx cache show)/mo-doc",
+    "bench": "mops bench"
   },
   "repository": {
     "type": "git",
@@ -30,11 +31,11 @@
   "devDependencies": {
     "execa": "^4.1.0",
     "fast-glob": "^3.3.2",
-    "ic-mops": "^1.1.1",
+    "ic-mops": "^1.4.0",
     "mo-dev": "^0.13.0",
     "npm-run-all": "^4.1.5",
     "prettier": "2",
     "prettier-plugin-motoko": "^0.10.5",
     "tsx": "^4.19.3"
   }
-}
+}
\ No newline at end of file


Reviews:
user: login: rvanasa
body: This is great! Thank you for setting this up! Preemptively approving so you can hopefully merge once it's ready.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T02:05:33Z
user: login: Kamirus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T12:46:56Z
user: login: Kamirus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T13:13:13Z
user: login: Kamirus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T13:15:28Z
user: login: ggreif
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T13:27:55Z
user: login: alexandru-uta
body: very cool, thanks!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T14:31:09Z
user: login: rvanasa
body: LGTM! Feel free to merge.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T19:33:03Z

Review comments:
diff_hunk: @@ -30,11 +31,11 @@
   "devDependencies": {
     "execa": "^4.1.0",
     "fast-glob": "^3.3.2",
-    "ic-mops": "^1.1.1",
+    "ic-mops": "^1.4.0",
path: package.json
user: login: Kamirus
body: Newest mops 1.4.0 is needed. [Here](https://github.com/ZenVoich/mops/issues/268#issuecomment-2743108161) is why.
created_at: 2025-03-24T12:46:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,90 @@
+name: Benchmarks
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+
+jobs:
+  benchmark:
+    runs-on: ubuntu-24.04
+    name: Run Benchmarks and Comment on PR or Upload on push
+
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: actions/setup-node@v4
+        with:
+          cache: 'npm'
+      - name: Cache mops packages
+        uses: actions/cache@v4
+        with:
+          key: mops-packages-${{ hashFiles('mops.toml') }}
+          restore-keys: |
+            mops-packages-${{ hashFiles('mops.toml') }}
+            mops-packages-
+          path: |
+            ~/.cache/mops
+      - run: npm ci
+      - run: npx mops toolchain init
+      - name: Install dfx
+        uses: dfinity/setup-dfx@main
+      - name: Install dfx cache
+        run: dfx cache install
path: .github/workflows/benchmarks.yml
user: login: Kamirus
body: Ideally we could have these steps separated out into a common action/workflow to be reused in other workflows (with optional `dfx` installation). Would be nice to have a common `setup` step for every workflow to make sure we install the same versions.
created_at: 2025-03-24T13:13:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,8 +7,10 @@ keywords = [ "base" ]
 license = "Apache-2.0"
 
 [dev-dependencies]
-matchers = "https://github.com/kritzcreek/motoko-matchers#v1.3.1@5ba5f52bd9a5649dedf5e2a1ccd55d98ed7ff982"
 test = "2.1.0"
+bench = "1.0.0"
+fuzz = "0.2.1"
+matchers = "https://github.com/kritzcreek/motoko-matchers#v1.3.1@5ba5f52bd9a5649dedf5e2a1ccd55d98ed7ff982"
path: mops.toml
user: login: Kamirus
body: `bench` and `matchers` require `base`. This reordering of dependencies helps mops resolve the correct `base` version...
created_at: 2025-03-24T13:15:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,90 @@
+name: Benchmarks
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+
+jobs:
+  benchmark:
+    runs-on: ubuntu-24.04
+    name: Run Benchmarks and Comment on PR or Upload on push
+
+    steps:
+      - uses: actions/checkout@v4
+
+      - uses: actions/setup-node@v4
+        with:
+          cache: 'npm'
+      - name: Cache mops packages
+        uses: actions/cache@v4
+        with:
+          key: mops-packages-${{ hashFiles('mops.toml') }}
+          restore-keys: |
+            mops-packages-${{ hashFiles('mops.toml') }}
+            mops-packages-
+          path: |
+            ~/.cache/mops
+      - run: npm ci
+      - run: npx mops toolchain init
+      - name: Install dfx
+        uses: dfinity/setup-dfx@main
+      - name: Install dfx cache
+        run: dfx cache install
path: .github/workflows/benchmarks.yml
user: login: ggreif
body: I think GH now supports factoring out action fragments. Maybe this: https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action
created_at: 2025-03-24T13:27:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-20T09:33:22Z
body: <!-- deploy-preview: do not delete/edit this line -->

author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-24T11:45:55Z
body: # Benchmark Results


Benchmark files:
• bench/FromIters.bench.mo

			
## Benchmarking the fromIter functions
			
_Columns describe the number of elements in the input iter._
			

Instructions

|                |                           100 |                           10_000 |                           100_000 |
| :------------- | ----------------------------: | -------------------------------: | --------------------------------: |
| Array.fromIter | 53_243 $({\color{gray}0\\%})$ | 5_152_204 $({\color{gray}0\\%})$ | 51_503_819 $({\color{gray}0\\%})$ |
| List.fromIter  | 39_313 $({\color{gray}0\\%})$ | 3_801_900 $({\color{gray}0\\%})$ | 38_004_901 $({\color{gray}0\\%})$ |
			

Heap

|                |                          100 |                       10_000 |                      100_000 |
| :------------- | ---------------------------: | ---------------------------: | ---------------------------: |
| Array.fromIter | 272 B $({\color{gray}0\\%})$ | 272 B $({\color{gray}0\\%})$ | 272 B $({\color{gray}0\\%})$ |
| List.fromIter  | 272 B $({\color{gray}0\\%})$ | 272 B $({\color{gray}0\\%})$ | 272 B $({\color{gray}0\\%})$ |
			

Garbage Collection

|                |                             100 |                            10_000 |                         100_000 |
| :------------- | ------------------------------: | --------------------------------: | ------------------------------: |
| Array.fromIter | 2.76 KiB $({\color{gray}0\\%})$ | 234.79 KiB $({\color{gray}0\\%})$ | 2.29 MiB $({\color{gray}0\\%})$ |
| List.fromIter  | 3.53 KiB $({\color{gray}0\\%})$ | 312.91 KiB $({\color{gray}0\\%})$ | 3.05 MiB $({\color{gray}0\\%})$ |
			
		
**Note**: Renamed benchmarks cannot be compared. Refer to the [current baseline](https://github.com/dfinity/new-motoko-base/tree/benchmark-results) for manual comparison.
author_association: NONE