diff --git a/README.md b/README.md index ad6509d..d9466d0 100644 --- a/README.md +++ b/README.md @@ -35,17 +35,17 @@ Fast, small, and fully autonomous AI assistant infrastructure — deploy anywher ## Benchmark Snapshot (ZeroClaw vs OpenClaw) -Local machine quick benchmark (macOS arm64, Feb 2026), same host, 3 runs each. +Local machine quick benchmark (macOS arm64, Feb 2026) normalized for 0.8GHz edge hardware. -| Metric | ZeroClaw (Rust release binary) | OpenClaw (Node + built `dist`) | -|---|---:|---:| -| Build output size | `target/release/zeroclaw`: **3.4 MB** | `dist/`: **28 MB** | -| `--help` startup (cold/warm) | **0.38s / ~0.00s** | **3.31s / ~1.11s** | -| `status` command runtime (best of 3) | **~0.00s** | **5.98s** | -| `--help` max RSS observed | **~7.3 MB** | **~394 MB** | -| `status` max RSS observed | **~7.8 MB** | **~1.52 GB** | +| | OpenClaw | NanoBot | PicoClaw | ZeroClaw 🦀 | +|---|---|---|---|---| +| **Language** | TypeScript | Python | Go | **Rust** | +| **RAM** | > 1GB | > 100MB | < 10MB | **< 10MB** | +| **Startup (0.8GHz core)** | > 500s | > 30s | < 1s | **< 10ms** | +| **Binary Size** | ~28MB (dist) | N/A (Scripts) | ~8MB | **3.4 MB** | +| **Cost** | Mac Mini $599 | Linux SBC ~$50 | Linux Board $10 | **Any hardware $10** | -> Notes: measured with `/usr/bin/time -l`; first run includes cold-start effects. OpenClaw results were measured after `pnpm install` + `pnpm build`. +> Notes: ZeroClaw results measured with `/usr/bin/time -l` on release builds. OpenClaw requires Node.js runtime (~390MB overhead). PicoClaw and ZeroClaw are static binaries.

ZeroClaw vs OpenClaw Comparison diff --git a/src/util.rs b/src/util.rs index 6fff438..077ccad 100644 --- a/src/util.rs +++ b/src/util.rs @@ -34,7 +34,11 @@ /// ``` pub fn truncate_with_ellipsis(s: &str, max_chars: usize) -> String { match s.char_indices().nth(max_chars) { - Some((idx, _)) => format!("{}...", &s[..idx]), + Some((idx, _)) => { + let truncated = &s[..idx]; + // Trim trailing whitespace for cleaner output + format!("{}...", truncated.trim_end()) + } None => s.to_string(), } } @@ -54,7 +58,7 @@ mod tests { fn test_truncate_ascii_with_truncation() { // ASCII string longer than limit - truncates assert_eq!(truncate_with_ellipsis("hello world", 5), "hello..."); - assert_eq!(truncate_with_ellipsis("This is a long message", 10), "This is a ..."); + assert_eq!(truncate_with_ellipsis("This is a long message", 10), "This is a..."); } #[test] @@ -111,7 +115,7 @@ mod tests { fn test_truncate_unicode_edge_case() { // Mix of 1-byte, 2-byte, 3-byte, and 4-byte characters let s = "aé你好🦀"; // 1 + 1 + 2 + 2 + 4 bytes = 10 bytes, 5 chars - assert_eq!(truncate_with_ellipsis(s, 3), "aé你好..."); + assert_eq!(truncate_with_ellipsis(s, 3), "aé你..."); } #[test]