diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e4a835e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: Do the thing in CI + +on: + push: + branches: ['master'] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + run-all: + runs-on: ubuntu-latest + steps: + # clone + - name: Checkout + uses: actions/checkout@v3 + # install dependencies + - uses: extractions/setup-just@v1 + - uses: oven-sh/setup-bun@v1 + # checks + - run: just setup + - run: just count diff --git a/justfile b/justfile index 9261adc..98b4f96 100644 --- a/justfile +++ b/justfile @@ -6,29 +6,43 @@ _default: just -l setup: + #!/usr/bin/env bash + set -euxo pipefail + if [ ! -z "${CI:-}" ]; then + if command -v apt-get >/dev/null 2>&1; then sudo apt-get install build-essential cargo clang curl hyperfine jq moreutils nodejs rustc; fi + if command -v deno >/dev/null 2>&1; then cargo install deno --locked; fi + if command -v rg >/dev/null 2>&1; then cargo install ripgrep --locked; fi + if command -v bun >/dev/null 2>&1; then curl -fsSL https://bun.sh/install | bash; fi + fi cd scripts && npm install prepare: rm -rf {{r}} {{b}} mkdir {{r}} {{b}} -node: - {{t}} node ./count.js 2> {{r}}/node.yml - {{t}} deno run --allow-all ./count.js 2> {{r}}/deno.yml - {{t}} bun run ./count.js 2> {{r}}/bun.yml - -python: - {{t}} python3 ./count.py 2> {{r}}/python.yml - -c: - gcc -O3 ./count.c -o {{b}}/c-gcc - {{t}} {{b}}/c-gcc 2> {{r}}/gcc.yml +build: prepare + gcc -O3 ./count.c -o {{b}}/c-gcc clang -O3 ./count.c -o {{b}}/c-clang - {{t}} {{b}}/c-clang 2> {{r}}/clang.yml - -rust: rustc -C opt-level=3 ./count.rs -o {{b}}/rust - {{t}} {{b}}/rust 2> {{r}}/rust.yml - -all: prepare node python c rust + echo "#!/usr/bin/env python3 \n$(cat count.py)" >> {{b}}/python3 + echo "#!/usr/bin/env node \n$(cat count.js)" >> {{b}}/node + echo "#!/usr/bin/env deno run \n$(cat count.js)" >> {{b}}/deno + echo "#!/usr/bin/env bun \n$(cat count.js)" >> {{b}}/bun + for f in {{b}}/*; do chmod +x "$f"; done + +run: build + #!/usr/bin/env bash + for f in {{b}}/*; do + out="{{r}}/$(basename $f).json" + hyperfine \ + --warmup 3 \ + --shell=none \ + --export-json "$out" \ + "$f" + jq '.results[0] | del(.exit_codes)' "$out" | sponge "$out" + timers "$f" >/dev/null 2>&1 + timers "$f" >/dev/null 2> >(jq '. += {"max_rss":'$(rg -oP '(?:max_rss:\s*)(\d+)' -r '$1')'}' "$out" | sponge "$out") + done + +count: run node ./scripts/summary.js \ No newline at end of file diff --git a/scripts/.npmrc b/scripts/.npmrc new file mode 100644 index 0000000..214c29d --- /dev/null +++ b/scripts/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org/ diff --git a/scripts/package-lock.json b/scripts/package-lock.json index 46e284f..317f536 100644 --- a/scripts/package-lock.json +++ b/scripts/package-lock.json @@ -1,12 +1,11 @@ { "name": "scripts", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { "human-readable": "^0.2.1", - "js-yaml": "^4.1.0", "pretty-bytes": "^6.1.1", "pretty-time": "^1.1.0" }, @@ -16,45 +15,32 @@ }, "node_modules/@types/node": { "version": "20.10.4", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/@types/node/-/node-20.10.4.tgz", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "node_modules/human-readable": { "version": "0.2.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/human-readable/-/human-readable-0.2.1.tgz", + "resolved": "https://registry.npmjs.org/human-readable/-/human-readable-0.2.1.tgz", "integrity": "sha512-uFtz4WZlB1M5xI45MZ5AjyAzfrrgLOdty4363Jd0LQ5NGXa+UiKaD0EQXQeDfCinodrpePFk/vKjzBlDTZdZQQ==" }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/pretty-bytes": { "version": "6.1.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", "engines": { "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/pretty-time": { "version": "1.1.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/pretty-time/-/pretty-time-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", "engines": { "node": ">=4" @@ -62,52 +48,7 @@ }, "node_modules/undici-types": { "version": "5.26.5", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - } - }, - "dependencies": { - "@types/node": { - "version": "20.10.4", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", - "dev": true, - "requires": { - "undici-types": "~5.26.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "human-readable": { - "version": "0.2.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/human-readable/-/human-readable-0.2.1.tgz", - "integrity": "sha512-uFtz4WZlB1M5xI45MZ5AjyAzfrrgLOdty4363Jd0LQ5NGXa+UiKaD0EQXQeDfCinodrpePFk/vKjzBlDTZdZQQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "pretty-bytes": { - "version": "6.1.1", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/pretty-bytes/-/pretty-bytes-6.1.1.tgz", - "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==" - }, - "pretty-time": { - "version": "1.1.0", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/pretty-time/-/pretty-time-1.1.0.tgz", - "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://packages.atlassian.com/api/npm/npm-remote/undici-types/-/undici-types-5.26.5.tgz", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true } diff --git a/scripts/package.json b/scripts/package.json index fc1472f..4a4c68b 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -2,7 +2,6 @@ "type": "module", "dependencies": { "human-readable": "^0.2.1", - "js-yaml": "^4.1.0", "pretty-bytes": "^6.1.1", "pretty-time": "^1.1.0" }, diff --git a/scripts/summary.js b/scripts/summary.js index 78cd05f..11a4522 100644 --- a/scripts/summary.js +++ b/scripts/summary.js @@ -1,7 +1,6 @@ import { readFile } from 'fs/promises'; import { readdirSync } from 'fs'; import { join } from 'path'; -import yaml from 'js-yaml'; import formatTime from 'pretty-time'; import formatSize from 'pretty-bytes'; @@ -9,14 +8,12 @@ const resultsDir = './results'; const results = await Promise.all( readdirSync(resultsDir).map(async (name) => { const text = await readFile(join(resultsDir, name), 'utf-8'); - const json = yaml.load(text.replace(/INFO \[timers\] /g, '').replace(/ -$/gm, ' null')); + const json = JSON.parse(text.replace(/INFO \[timers\] /g, '').replace(/ -$/gm, ' null')); - const rss_split = json['max_rss'].indexOf(' '); + console.log(json); return { - name: [name, json['cmdline']].join(' :: '), - real: parseInt(json['real'].replace('ns', '')), - rss: parseInt(json['max_rss'].substring(0, rss_split)), - rss_fmt: json['max_rss'].substring(rss_split), + name: [name, json.command].join(' :: '), + ...json }; }) ); @@ -24,13 +21,16 @@ const results = await Promise.all( console.table( results .slice() - .sort((a, b) => a.real - b.real) - .map(({ name, real }) => ({ name, real: formatTime(real) })) + .sort((a, b) => a.mean - b.mean) + .map(({ name, mean }) => ({ + name, + mean: formatTime(Math.floor(mean * 1_000_000_000), undefined, 5), + })) ); console.table( results .slice() - .sort((a, b) => a.rss - b.rss) - .map(({ name, rss }) => ({ name, rss: formatSize(rss, { minimumFractionDigits: 7 }) })) + .sort((a, b) => a.max_rss - b.max_rss) + .map(({ name, max_rss }) => ({ name, max_rss: formatSize(max_rss, { minimumFractionDigits: 7 }) })) );