{"id":28906800,"url":"https://github.com/goptics/vizb","last_synced_at":"2026-05-23T09:01:23.295Z","repository":{"id":299633402,"uuid":"1003638795","full_name":"goptics/vizb","owner":"goptics","description":"A 4D visualizer for go benchmarks from your local to CI/CD pipeline","archived":false,"fork":false,"pushed_at":"2026-05-21T14:09:47.000Z","size":4421,"stargazers_count":69,"open_issues_count":4,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-21T14:32:18.031Z","etag":null,"topics":["benchmark","benchmarking","chart","ci-cd","cli","github-actions","go","golang","golang-benchmark","golang-tools","visualizer"],"latest_commit_sha":null,"homepage":"https://goptics.github.io/vizb","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/goptics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-17T12:53:37.000Z","updated_at":"2026-05-21T14:16:08.000Z","dependencies_parsed_at":"2025-09-18T08:27:34.369Z","dependency_job_id":"16069201-61c7-49d6-a350-3664b2c94bf4","html_url":"https://github.com/goptics/vizb","commit_stats":null,"previous_names":["goptics/vizb"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/goptics/vizb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goptics%2Fvizb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goptics%2Fvizb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goptics%2Fvizb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goptics%2Fvizb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/goptics","download_url":"https://codeload.github.com/goptics/vizb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goptics%2Fvizb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33389229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmark","benchmarking","chart","ci-cd","cli","github-actions","go","golang","golang-benchmark","golang-tools","visualizer"],"created_at":"2025-06-21T15:09:55.444Z","updated_at":"2026-05-23T09:01:23.274Z","avatar_url":"https://github.com/goptics.png","language":"Go","funding_links":[],"categories":["Benchmarks"],"sub_categories":["Other Software"],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assests/logo.png\" alt=\"vizb logo\" width=\"120\" height=\"auto\" /\u003e\n  \u003ch1\u003eVizb\u003c/h1\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/avelino/awesome-go?tab=readme-ov-file#benchmarks\"\u003e\u003cimg src=\"https://awesome.re/mentioned-badge-flat.svg\" alt=\"Mentioned in Awesome Go\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://goptics.github.io/vizb/examples/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Live-Examples-orange?style=for\" alt=\"Examples\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/goptics/vizb\"\u003e\u003cimg src=\"https://img.shields.io/badge/go-pkg-00ADD8.svg?logo=go\" alt=\"Go Reference\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/goptics/vizb\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/goptics/vizb\" alt=\"Go Report Card\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/goptics/vizb/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/goptics/vizb/actions/workflows/ci.yml/badge.svg\" alt=\"CI\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/goptics/vizb\"\u003e\u003cimg src=\"https://codecov.io/gh/goptics/vizb/branch/main/graph/badge.svg\" alt=\"Codecov\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://golang.org/doc/devel/release.html\"\u003e\u003cimg src=\"https://img.shields.io/badge/Go-1.24+-00ADD8?style=for\u0026logo=go\" alt=\"Go Version\" /\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg?style=for\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    A CLI tool that transforms Go benchmark raw output into interactive \u003cstrong\u003e4D visualizations\u003c/strong\u003e. It allows you to \u003ca href=\"#merging-multiple-benchmarks\"\u003emerge multiple benchmark data\u003c/a\u003e, apply \u003ca href=\"#advance-usage\"\u003eadvanced grouping logic\u003c/a\u003e, and explore performance across four dimensions: Source, Group, and two customizable axes (X and Y). Available \u003cstrong\u003e\u003ca href=\"#github-action\"\u003eGitHub Action\u003c/a\u003e\u003c/strong\u003e for seamless CI pipeline integration — all within a single deployable HTML file.\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## Features\n\n- **Modern Interactive UI**: Robust **Vue.js** application with a smooth and responsive experience.\n- **Multi-Chart**: Supports multiple charts (`bar`, `line` and `pie`) in a single place.\n- **Sorting**: Sort data (`asc`/`desc`) for comparison through UI settings or CLI flags.\n- **Swap Axis**: Swap the `n`, `x` and `y` axes for diverse comparison through UI settings.\n- **Logarithmic Scale**: Use `--scale log` for bar and line charts to better visualize benchmarks with high variance in values.\n- **Multi-Dimensional Grouping**: Merge multiple benchmark data for deep comparative analysis.\n- **Tag-Based Merging**: Tag benchmarks with commit hashes or version labels to compare performance across releases with automatic data merging.\n- **Flexible Input**: Automatically processes raw `go test -bench` output and the standard JSON output of `go test -bench -json`.\n- **Comprehensive Metrics**: Compare time, memory, and numbers with customizable units.\n- **Smart Grouping**: Extract grouping logic from benchmark names using regex and group patterns.\n- **Filtering**: Filter benchmarks to include only those matching a regex pattern.\n- **Export Options**: Generate `single-file` HTML/JSON and options to save charts as `JPEG`.\n- **GitHub Action**: First-class CI support — run benchmarks, tag releases, merge history, and deploy visualizations directly from your workflows with a single composite action.\n- **Release Guard**: Manual approval gate — push a tag, review in the Actions UI, and approve before GoReleaser publishes.\n\n## Installation\n\n### Go Toolchain\n\n```bash\ngo install github.com/goptics/vizb@latest\n```\n\n### Download Binary\n\nPre-built binaries for Linux, macOS, and Windows are available on the [releases page](https://github.com/goptics/vizb/releases).\n\n## Basic Usage\n\n### Using raw benchmark output\n\nRun your Go benchmarks and save the output:\n\n```bash\ngo test -bench . \u003e bench.txt\n```\n\nGenerate charts from the benchmark:\n\n```bash\nvizb bench.txt -o output.html\n```\n\n### Direct piping\n\nPipe benchmark results directly to vizb:\n\n```bash\n# Raw output\ngo test -bench . | vizb -o output.html\n\n# JSON output (automatically detected and converted)\ngo test -bench . -json | vizb -o output.html\n```\n\n### Using vizb standard JSON benchmark output\n\n```bash\nvizb bench.txt -o output.json\n```\n\nGenerate charts from the standard JSON benchmark data:\n\n```bash\nvizb output.json -o output.html\n```\n\n### Using logarithmic scale\n\nFor benchmarks with high variance in values (e.g., 1 to 1,000,000), use the logarithmic Y-axis scale:\n\n```bash\nvizb bench.txt -o output.html --scale log\n```\n\nThe `--scale` flag accepts `linear` (default) or `log`. It works with bar and line charts; pie charts and 1D data automatically use linear scale.\n\n### Merging multiple benchmarks\n\nYou can combine multiple benchmark JSON files using the `merge` command. This is useful for aggregating benchmark data from different runs, machines, or environments. The merge command always outputs JSON — use `vizb html` to render the result as an interactive HTML chart.\n\n```bash\n# Merge specific files into JSON\nvizb merge output.json output2.json -o merged.json\n\n# Generate HTML from merged JSON\nvizb html merged.json -o merged_report.html\n\n# Merge all JSON files in a directory\nvizb merge ./results/ -o all.json\n\n# Mix and match files and directories\nvizb merge ./old_results/ output.json -o comparison.json\n```\n\nOpen the generated HTML file in your browser to view the interactive charts.\n\n\u003e [!Note]\n\u003e The `merge` command requires JSON files as input, which must be generated using `vizb bench.txt -o output.json`.\n\n### Tag-Based Merging\n\nVizb supports tagging benchmarks to compare performance across multiple commits, releases, or environment variants. The `--tag` flag on the main command assigns a label (e.g., commit hash, version number) to a benchmark run. When merging, vizb groups benchmarks by `name` and deep-merges those sharing the same name but different tags into a single object, preserving all timestamps, history, and data.\n\n#### Tagging a benchmark run\n\n```bash\nvizb bench-v1.txt -o v1.json --tag v1 -n \"Foo\"\n\nvizb bench-v2.txt -o v2.json --tag v2 -n \"Foo\"\n```\n\n#### How tag-based merging works\n\nWhen you merge benchmarks sharing the same name with different tags:\n\n```bash\nvizb merge v1.json v2.json -o comparison.json\nvizb html comparison.json -o comparison.html\n```\n\nVizb groups benchmarks by name and processes each group as follows:\n\n1. **Deduplication**: If two entries share the same name and tag, only the one with the latest timestamp is kept. Older entries are discarded.\n2. **Inner merge**: Entries with different tags are deep-merged into a single benchmark. Data points are sorted in chronological tag order and each is annotated with its originating tag.\n3. **Legacy entries**: Untagged benchmarks (no `--tag`) with the same name are deduplicated (first-seen wins) and their data is prepended before tagged entries.\n4. **Output**: The merged benchmark retains the latest tag (by timestamp), carries a history of older tags, and includes data from all runs.\n\n#### Controlling where the tag is injected\n\nBy default, the tag is injected into the `name` dimension of each inner data object. Use `--tag-axis` (shorthand `-A`) to target `xAxis` or `yAxis` instead:\n\n```bash\n# Inject tag into xAxis so the X-axis labels show version differences\nvizb merge v1.json v2.json -A x -o comparison.json\nvizb html comparison.json -o comparison.html\n```\n\nAccepted values: `n` (name), `x` (xAxis), `y` (yAxis). Default is `n`.\n\n## Advance Usage\n\n### How vizb groups your benchmark data\n\nVizb creates charts that make sense by putting your benchmark data into logical groupings and axes. It sees the data as `1D` (xAxis) by default, but if you have to deal with `2D` or `3D` data, you can use the `--group-pattern` and `--group-regex` flags to group your data.\n\n### Understanding Group Patterns\n\nA group pattern tells vizb how to dissect your benchmark names into three key components:\n\n1. **Name (n)**: The family or group the benchmark belongs to. Benchmarks with the same `Name` will be grouped together in the same chart. (optional)\n2. **XAxis (x)**: The category that goes on the X-axis (e.g., input size, concurrency level).\n3. **YAxis (y)**: The specific test case or variation (e.g., algorithm name, sub-test).\n\n### Visualizing the Extraction\n\nImagine you have a benchmark named `BenchmarkSort/100/Ints`, which has `3D` data.\n\nIf you use the pattern `name/xAxis/yAxis` (or `n/x/y`), vizb splits the name wherever it finds a `/`:\n\n```text\nBenchmark Name:  BenchmarkSort  /  100  /  Ints\n                     │              │        │\nPattern:           [Name]        [XAxis]   [YAxis]\n                     │              │        │\nResult:            \"Sort\"         \"100\"    \"Ints\"\n```\n\n### Group Pattern Syntax (`--group-pattern`)\n\n- **Components**: Use `name`, `xAxis`, `yAxis` (or shorthands `n`, `x`, `y`).\n- **Separators**: Use `/` (slash) or `_` (underscore) to match the separators in your benchmark names.\n- **Skipping parts**: You can leave parts empty in the pattern to ignore sections of the benchmark name.\n\n#### Standard Go Benchmarks (Slash Separated)\n\nFormat: `Benchmark\u003cGroup\u003e/\u003cInputSize\u003e/\u003cVariant\u003e`\n\n**Pattern:** `n/x/y`\n\n| Benchmark Name                 | Extracted Data                                            |\n| :----------------------------- | :-------------------------------------------------------- |\n| `BenchmarkSort/1024/QuickSort` | **Name:** `Sort` **XAxis:** `1024` **YAxis:** `QuickSort` |\n| `BenchmarkSort/1024/MergeSort` | **Name:** `Sort` **XAxis:** `1024` **YAxis:** `MergeSort` |\n\n#### Underscore Separated\n\nFormat: `Benchmark\u003cGroup\u003e_\u003cVariant\u003e_\u003cInputSize\u003e`\n\n**Pattern:** `n_y_x`\n\n| Benchmark Name             | Extracted Data                                        |\n| :------------------------- | :---------------------------------------------------- |\n| `BenchmarkHash_SHA256_1KB` | **Name:** `Hash` **YAxis:** `SHA256` **XAxis:** `1KB` |\n| `BenchmarkHash_MD5_1KB`    | **Name:** `Hash` **YAxis:** `MD5` **XAxis:** `1KB`    |\n\n#### Simple Grouping (No X-Axis)\n\nFormat: `Benchmark\u003cGroup\u003e/\u003cVariant\u003e`\n\n**Pattern:** `n/y`\n\n| Benchmark Name            | Extracted Data                                               |\n| :------------------------ | :----------------------------------------------------------- |\n| `BenchmarkJSON/Marshal`   | **Name:** `JSON` **XAxis:** _(empty)_ **YAxis:** `Marshal`   |\n| `BenchmarkJSON/Unmarshal` | **Name:** `JSON` **XAxis:** _(empty)_ **YAxis:** `Unmarshal` |\n\n#### Ignoring Prefixes\n\nSometimes you might want to ignore a common prefix or a specific part of the name.\n\n**Pattern:** `/n/y` (Starts with a separator to skip the first part)\n\n| Benchmark Name               | Extracted Data                                                         |\n| :--------------------------- | :--------------------------------------------------------------------- |\n| `BenchmarkTest/JSON/Marshal` | **Name:** `JSON` **YAxis:** `Marshal` _(First part \"Test\" is ignored)_ |\n\n### Group Regex Syntax (`--group-regex`)\n\nFor more complex benchmark names where simple patterns aren't enough, you can use Regular Expressions with named groups.\n\n- **Named Groups**: Use `(?\u003cname\u003e...)`, `(?\u003cxAxis\u003e...)`, `(?\u003cyAxis\u003e...)` (or shorthands `(?\u003cn\u003e...)`, `(?\u003cx\u003e...)`, `(?\u003cy\u003e...)`) to capture parts of the benchmark name.\n- **Flexibility**: Regex allows you to match specific characters, ignore parts, and handle irregular formats.\n\n#### Examples\n\n| Benchmark Name                            | Regex                                   | Extracted Data                                            | Dimensions |\n| :---------------------------------------- | :-------------------------------------- | :-------------------------------------------------------- | :--------- |\n| `BenchmarkHashing64MD5`                   | `Hashing64(?\u003cx\u003e.*)`                     | **XAxis:** `MD5`                                          | 1D         |\n| `BenchmarkJSONByMarshal`                  | `(?\u003cx\u003e.*)By(?\u003cy\u003e.*)`                    | **XAxis:** `JSON` **YAxis:** `Marshal`                    | 2D         |\n| `BenchmarkDecode/text=digits/level=speed` | `(?\u003cn\u003e.*)/text=(?\u003cx\u003e.*)/level=(?\u003cy\u003e.*)` | **Name:** `Decode` **XAxis:** `digits` **YAxis:** `speed` | 3D         |\n\n\u003e [!Note]\n\u003e You must specify at least one of the `x` and `y` axes when you use the `--group-[pattern|regex]` command. the `n` is optional.\n\n\n## GitHub Action\n\nVizb provides a composite GitHub Action to run benchmarks and generate visualizations in CI.\n\n### Basic Usage\n\n```yaml\n- uses: actions/setup-go@v6\n  with:\n    go-version-file: go.mod\n\n- uses: goptics/vizb@v0\n  with:\n    bench-cmd: \"go test -bench=.\"\n    output-html: pages/index.html\n```\n\n### Tracking Performance Across Releases\n\nTag benchmarks with release versions, merge historical data, and deploy charts:\n\n```yaml\non:\n  push:\n    tags: ['v*']\n\njobs:\n  bench:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: go.mod\n\n      - name: Download previous benchmark data\n        uses: dawidd6/action-download-artifact@v21\n        continue-on-error: true\n        with:\n          workflow: bench.yml\n          name: merged.json\n          path: prev\n\n      - uses: goptics/vizb@v0\n        with:\n          bench-cmd: \"go test -bench=.\"\n          tag: ${{ github.ref_name }}\n          merge-dir: prev\n          tag-axis: x\n          output-json: merged.json\n          output-html: pages/index.html\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: merged.json\n          path: merged.json\n\n      - uses: peaceiris/actions-gh-pages@v4\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: pages\n```\n\n\u003e [!Note]\n\u003e The `tag-axis` input controls which data dimension receives the tag annotation. Use `x` to show versions on the X-axis for clean progressive comparison.\n\n## Development\n\nThis project uses [Task](https://taskfile.dev/) for managing development workflows.\n\n### Setup Development Environment\n\n```bash\n# Install Task runner\ngo install github.com/go-task/task/v3/cmd/task@latest\n```\n\n### Available Tasks\n\n```bash\n# install dependencies\ntask init\n\n# Run the UI in development mode\ntask dev:ui\n\n# Build The UI\ntask build:ui\n\n# Build the binary (run from ./bin/vizb)\ntask build:cli\n\n# Build everything\ntask build\n\n# Run tests\ntask test\n```\n\n## Contributing\n\nContributions are welcome! Feel free to open issues or submit pull requests.\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoptics%2Fvizb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoptics%2Fvizb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoptics%2Fvizb/lists"}