From 02d2c7cae10c42c8ed261ea02b1b3a493f767388 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Dec 2025 20:42:03 +0000 Subject: [PATCH] Add file_io benchmark for testing file I/O performance New benchmark writes n bytes to a temp file, reads them back, and computes a checksum. Tests file write/read throughput across C, Python, JavaScript, Ruby, and Hemlock implementations. --- benchmarks/file_io/file_io.c | 52 ++++++++++++++++++++++++++++++++++ benchmarks/file_io/file_io.hml | 49 ++++++++++++++++++++++++++++++++ benchmarks/file_io/file_io.js | 27 ++++++++++++++++++ benchmarks/file_io/file_io.py | 24 ++++++++++++++++ benchmarks/file_io/file_io.rb | 22 ++++++++++++++ run.sh | 7 +++-- 6 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 benchmarks/file_io/file_io.c create mode 100644 benchmarks/file_io/file_io.hml create mode 100644 benchmarks/file_io/file_io.js create mode 100644 benchmarks/file_io/file_io.py create mode 100644 benchmarks/file_io/file_io.rb diff --git a/benchmarks/file_io/file_io.c b/benchmarks/file_io/file_io.c new file mode 100644 index 0000000..11144fd --- /dev/null +++ b/benchmarks/file_io/file_io.c @@ -0,0 +1,52 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + int n = argc > 1 ? atoi(argv[1]) : 1000000; + + // Create temp file + char filename[] = "/tmp/barbell_file_io_XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) { + perror("mkstemp"); + return 1; + } + close(fd); + + // Write n bytes + FILE *f = fopen(filename, "wb"); + if (!f) { + perror("fopen write"); + return 1; + } + + unsigned char *buf = malloc(n); + for (int i = 0; i < n; i++) { + buf[i] = (unsigned char)(i % 256); + } + fwrite(buf, 1, n, f); + fclose(f); + + // Read back and sum + f = fopen(filename, "rb"); + if (!f) { + perror("fopen read"); + return 1; + } + + size_t bytes_read = fread(buf, 1, n, f); + fclose(f); + + long sum = 0; + for (size_t i = 0; i < bytes_read; i++) { + sum += buf[i]; + } + + // Cleanup + free(buf); + unlink(filename); + + printf("%ld\n", sum); + return 0; +} diff --git a/benchmarks/file_io/file_io.hml b/benchmarks/file_io/file_io.hml new file mode 100644 index 0000000..983af25 --- /dev/null +++ b/benchmarks/file_io/file_io.hml @@ -0,0 +1,49 @@ +// File I/O benchmark - Hemlock + +fn parse_int(s) { + let result = 0; + let idx = 0; + while (idx < s.length) { + let ch = s[idx]; + let code: i32 = ch; + let zero: i32 = '0'; + result = result * 10 + (code - zero); + idx = idx + 1; + } + return result; +} + +let n = 1000000; +if (args.length > 1) { + n = parse_int(args[1]); +} + +// Create temp filename +let filename = "/tmp/barbell_file_io_hemlock.tmp"; + +// Build data to write (bytes 0-255 repeating) +let data = []; +let i = 0; +while (i < n) { + data.push(i % 256); + i = i + 1; +} + +// Write to file +write_file(filename, data); + +// Read back from file +let read_data = read_file(filename); + +// Sum all bytes +let sum = 0; +i = 0; +while (i < read_data.length) { + sum = sum + read_data[i]; + i = i + 1; +} + +// Delete file +delete_file(filename); + +print(sum); diff --git a/benchmarks/file_io/file_io.js b/benchmarks/file_io/file_io.js new file mode 100644 index 0000000..3c861b3 --- /dev/null +++ b/benchmarks/file_io/file_io.js @@ -0,0 +1,27 @@ +const fs = require('fs'); +const os = require('os'); +const path = require('path'); + +const n = parseInt(process.argv[2]) || 1000000; + +// Create temp file +const filename = path.join(os.tmpdir(), `barbell_file_io_${process.pid}_${Date.now()}`); + +// Write n bytes +const buf = Buffer.alloc(n); +for (let i = 0; i < n; i++) { + buf[i] = i % 256; +} +fs.writeFileSync(filename, buf); + +// Read back and sum +const readBuf = fs.readFileSync(filename); +let sum = 0; +for (let i = 0; i < readBuf.length; i++) { + sum += readBuf[i]; +} + +// Cleanup +fs.unlinkSync(filename); + +console.log(sum); diff --git a/benchmarks/file_io/file_io.py b/benchmarks/file_io/file_io.py new file mode 100644 index 0000000..e18521f --- /dev/null +++ b/benchmarks/file_io/file_io.py @@ -0,0 +1,24 @@ +import sys +import os +import tempfile + +n = int(sys.argv[1]) if len(sys.argv) > 1 else 1000000 + +# Create temp file +fd, filename = tempfile.mkstemp(prefix='barbell_file_io_') +os.close(fd) + +try: + # Write n bytes + data = bytes(i % 256 for i in range(n)) + with open(filename, 'wb') as f: + f.write(data) + + # Read back and sum + with open(filename, 'rb') as f: + read_data = f.read() + + total = sum(read_data) + print(total) +finally: + os.unlink(filename) diff --git a/benchmarks/file_io/file_io.rb b/benchmarks/file_io/file_io.rb new file mode 100644 index 0000000..cd73387 --- /dev/null +++ b/benchmarks/file_io/file_io.rb @@ -0,0 +1,22 @@ +require 'tempfile' + +n = ARGV[0] ? ARGV[0].to_i : 1000000 + +# Create temp file +file = Tempfile.new('barbell_file_io_') +filename = file.path +file.close + +begin + # Write n bytes + data = (0...n).map { |i| (i % 256).chr }.join.b + File.binwrite(filename, data) + + # Read back and sum + read_data = File.binread(filename) + total = read_data.bytes.sum + + puts total +ensure + File.unlink(filename) if File.exist?(filename) +end diff --git a/run.sh b/run.sh index 414b181..a889cf2 100755 --- a/run.sh +++ b/run.sh @@ -28,7 +28,7 @@ usage() { echo " --iter N Number of iterations (default: 3)" echo " --help, -h Show this help" echo "" - echo "Benchmarks: fib, array_sum, string_concat, primes_sieve" + echo "Benchmarks: fib, array_sum, string_concat, primes_sieve, file_io" echo " (leave empty to run all)" } @@ -72,6 +72,9 @@ get_input() { primes_sieve) [[ $QUICK_MODE -eq 1 ]] && echo 100000 || echo 1000000 ;; + file_io) + [[ $QUICK_MODE -eq 1 ]] && echo 100000 || echo 1000000 + ;; esac } @@ -195,7 +198,7 @@ run_all() { if [[ -n "$BENCHMARK" ]]; then benchmarks="$BENCHMARK" else - benchmarks="fib array_sum string_concat primes_sieve" + benchmarks="fib array_sum string_concat primes_sieve file_io" fi local languages="c hemlockc hemlock python javascript ruby"