{"id":45518419,"url":"https://github.com/myk12397/mach","last_synced_at":"2026-02-27T01:00:42.192Z","repository":{"id":339648450,"uuid":"1162831209","full_name":"MYK12397/mach","owner":"MYK12397","description":"lightning fast zero-allocation, structured, leveled logging in Go.","archived":false,"fork":false,"pushed_at":"2026-02-20T19:10:57.000Z","size":13,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-23T00:37:57.016Z","etag":null,"topics":["golang","logging","structured-logging"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MYK12397.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2026-02-20T18:46:53.000Z","updated_at":"2026-02-22T11:12:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MYK12397/mach","commit_stats":null,"previous_names":["myk12397/mach"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/MYK12397/mach","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MYK12397%2Fmach","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MYK12397%2Fmach/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MYK12397%2Fmach/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MYK12397%2Fmach/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MYK12397","download_url":"https://codeload.github.com/MYK12397/mach/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MYK12397%2Fmach/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29758021,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T21:02:23.375Z","status":"ssl_error","status_checked_at":"2026-02-23T20:58:31.539Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["golang","logging","structured-logging"],"created_at":"2026-02-22T21:50:09.885Z","updated_at":"2026-02-26T00:01:41.833Z","avatar_url":"https://github.com/MYK12397.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mach\n \nA zero-allocation structured, leveled JSON logger for Go, built on [gohotpool](https://github.com/MYK12397/gohotpool).\n \n**2x faster than zap. 3-5x faster than slog. Zero allocations.**\n \n## Why\n \nEvery structured logger in Go pays the same costs: buffer allocation, JSON encoding overhead, interface boxing for field values, and lock contention under parallelism. mach eliminates all of them:\n \n- **Buffer pooling via gohotpool** — per-P (processor) cached byte buffers with clock-sweep eviction. No `sync.Pool` GC jitter, no allocation on the hot path.\n- **Typed fields** — `Field` structs carry data in fixed-size `int64`/`string` slots selected by a type tag, avoiding `interface{}` heap escapes entirely.\n- **Hand-rolled JSON encoding** — all encoding functions operate directly on `[]byte` with zero intermediate allocations. String escaping uses a bulk-scan fast path over safe ASCII ranges.\n- **No logger-level mutex** — each goroutine encodes into its own pooled buffer and writes directly to the output. Locking is opt-in at the writer level via `SyncWriter()`.\n \n## Install\n\n```\ngo get github.com/MYK12397/mach\n```\n\nmach is a standalone package with a single external dependency on [gohotpool](https://github.com/MYK12397/gohotpool).\n\n## Usage\n \n```go\npackage main\n \nimport (\n    \"os\"\n    \"time\"\n \n    \"github.com/MYK12397/mach\"\n)\n \nfunc main() {\n    log := mach.New(mach.Config{\n        Output: mach.SyncWriter(os.Stdout),\n        Level:  mach.InfoLevel,\n    })\n \n    log.Info(\"server started\",\n        mach.String(\"addr\", \":8080\"),\n        mach.Int(\"workers\", 4),\n    )\n \n    reqLog := log.With(\n        mach.String(\"service\", \"api\"),\n        mach.String(\"version\", \"1.2.0\"),\n    )\n \n    reqLog.Info(\"request handled\",\n        mach.String(\"method\", \"GET\"),\n        mach.String(\"path\", \"/users\"),\n        mach.Int(\"status\", 200),\n        mach.Duration(\"latency\", 1200*time.Microsecond),\n    )\n \n    reqLog.Error(\"query failed\",\n        mach.Err(os.ErrNotExist),\n        mach.String(\"table\", \"users\"),\n    )\n}\n```\n \nOutput:\n \n```json\n{\"level\":\"INFO\",\"ts\":\"2026-02-17T22:30:00.123456789Z\",\"msg\":\"server started\",\"addr\":\":8080\",\"workers\":4}\n{\"level\":\"INFO\",\"ts\":\"2026-02-17T22:30:00.123556789Z\",\"msg\":\"request handled\",\"service\":\"api\",\"version\":\"1.2.0\",\"method\":\"GET\",\"path\":\"/users\",\"status\":200,\"latency\":0.0012}\n{\"level\":\"ERROR\",\"ts\":\"2026-02-17T22:30:00.123656789Z\",\"msg\":\"query failed\",\"service\":\"api\",\"version\":\"1.2.0\",\"error\":\"file does not exist\",\"table\":\"users\"}\n```\n \n## API\n \n### Logger\n \n```go\nmach.New(cfg Config) *Logger\n \nlogger.Debug(msg string, fields ...Field)\nlogger.Info(msg string, fields ...Field)\nlogger.Warn(msg string, fields ...Field)\nlogger.Error(msg string, fields ...Field)\nlogger.Fatal(msg string, fields ...Field)   // calls os.Exit(1)\n \nlogger.With(fields ...Field) *Logger        // child logger with pre-encoded context\nlogger.SetLevel(level Level)                // change level at runtime (atomic)\n```\n \n### Fields\n \n```go\nmach.String(key, val string)\nmach.Int(key string, val int)\nmach.Int64(key string, val int64)\nmach.Float64(key string, val float64)\nmach.Bool(key string, val bool)\nmach.Duration(key string, val time.Duration)\nmach.Time(key string, val time.Time)\nmach.Err(val error)                    // key is \"error\"\nmach.Bytes(key string, val []byte)\n```\n \n### Writer Safety\n \nmach does not hold a logger-level mutex. The output `io.Writer` is called directly from each goroutine. For writers that aren't inherently thread-safe, wrap them:\n \n```go\nmach.New(mach.Config{\n    Output: mach.SyncWriter(file), // adds a mutex\n})\n```\n \n`io.Discard`, and `os.File` writes under `PIPE_BUF` (4KB on Linux) are already atomic at the OS level and don't need wrapping.\n \n## Benchmark\n \nAll benchmarks write to `io.Discard` to isolate pure encoding speed. Run with:\n \n```\ngo test -bench=. -benchmem -count=3\n```\n \n### Results (Apple M4 Pro, Go 1.23.1)\n \n```\ngoos: darwin\ngoarch: arm64\ncpu: Apple M4 Pro\n \nBenchmarkSimple_Mach-12                       75 ns/op     0 B/op    0 allocs/op\nBenchmarkSimple_Zap-12                       176 ns/op     0 B/op    0 allocs/op\nBenchmarkSimple_Slog-12                      272 ns/op     0 B/op    0 allocs/op\n \nBenchmarkFiveFields_Mach-12                  163 ns/op     0 B/op    0 allocs/op\nBenchmarkFiveFields_Zap-12                   349 ns/op   320 B/op    1 allocs/op\nBenchmarkFiveFields_Slog-12                  563 ns/op   240 B/op    5 allocs/op\n \nBenchmarkTenFields_Mach-12                   262 ns/op     0 B/op    0 allocs/op\nBenchmarkTenFields_Zap-12                    544 ns/op   705 B/op    1 allocs/op\nBenchmarkTenFields_Slog-12                  1031 ns/op   808 B/op   14 allocs/op\n \nBenchmarkWithContext_Mach-12                 100 ns/op     0 B/op    0 allocs/op\nBenchmarkWithContext_Zap-12                  242 ns/op   128 B/op    1 allocs/op\nBenchmarkWithContext_Slog-12                 392 ns/op    96 B/op    2 allocs/op\n \nBenchmarkDisabled_Mach-12                    6.3 ns/op    0 B/op    0 allocs/op\nBenchmarkDisabled_Zap-12                      22 ns/op  128 B/op    1 allocs/op\nBenchmarkDisabled_Slog-12                     32 ns/op   96 B/op    2 allocs/op\n \nBenchmarkParallel_Mach-12                     66 ns/op    0 B/op    0 allocs/op\nBenchmarkParallel_Zap-12                      96 ns/op  256 B/op    1 allocs/op\nBenchmarkParallel_Slog-12                    239 ns/op  192 B/op    4 allocs/op\n \nBenchmarkLargePayload_Mach-12               473 ns/op    0 B/op    0 allocs/op\nBenchmarkLargePayload_Zap-12               1024 ns/op  320 B/op    1 allocs/op\nBenchmarkLargePayload_Slog-12              1351 ns/op  360 B/op    8 allocs/op\n \nBenchmarkError_Mach-12                      123 ns/op    0 B/op    0 allocs/op\nBenchmarkError_Zap-12                       288 ns/op  192 B/op    1 allocs/op\nBenchmarkError_Slog-12                      457 ns/op  144 B/op    3 allocs/op\n \nBenchmarkParallelWithContext_Mach-12          63 ns/op    0 B/op    0 allocs/op\nBenchmarkParallelWithContext_Zap-12           98 ns/op  256 B/op    1 allocs/op\nBenchmarkParallelWithContext_Slog-12         241 ns/op  192 B/op    4 allocs/op\n```\n \n### Summary\n \n| Scenario | mach | zap | slog | vs zap | vs slog |\n|---|---|---|---|---|---|\n| Simple (no fields) | **75 ns** | 176 ns | 272 ns | 2.3x faster | 3.6x faster |\n| 5 fields (mixed types) | **163 ns** | 349 ns | 563 ns | 2.1x faster | 3.5x faster |\n| 10 fields | **262 ns** | 544 ns | 1031 ns | 2.1x faster | 3.9x faster |\n| With() context | **100 ns** | 242 ns | 392 ns | 2.4x faster | 3.9x faster |\n| Disabled level | **6.3 ns** | 22 ns | 32 ns | 3.5x faster | 5.1x faster |\n| Parallel (12 cores) | **66 ns** | 96 ns | 239 ns | 1.5x faster | 3.6x faster |\n| Large payload (1KB) | **473 ns** | 1024 ns | 1351 ns | 2.2x faster | 2.9x faster |\n| Error with fields | **123 ns** | 288 ns | 457 ns | 2.3x faster | 3.7x faster |\n| Parallel + context | **63 ns** | 98 ns | 241 ns | 1.6x faster | 3.8x faster |\n \n**Zero allocations across every benchmark.** Zap allocates 1 per log (128-705 bytes). Slog allocates 2-14 per log.\n \n### Why mach is faster\n \n| Technique | What it avoids |\n|---|---|\n| gohotpool per-P buffer cache | `sync.Pool` overhead + GC jitter |\n| Typed `Field` struct with `int64`/`string` slots | `interface{}` heap escapes |\n| Direct `[]byte` append encoding | Encoder pointer indirection |\n| Bulk-scan string escaping | Per-byte branch for safe ASCII |\n| No logger-level mutex | Goroutine serialization under parallelism |\n| Pre-encoded `With()` context | Re-encoding context fields on every log |\n| Atomic level check short-circuits before variadic alloc | Wasted work on disabled levels |\n \n## Design\n \n```\nlog.Info(\"msg\", fields...)\n  |\n  +-- atomic level check (6ns, short-circuits if disabled)\n  |\n  +-- gohotpool.Get() (per-P cache hit: ~5ns, 0 allocs)\n  |\n  +-- encode JSON into local []byte\n  |     +-- level string (constant)\n  |     +-- timestamp via time.Now().AppendFormat (no temp string)\n  |     +-- message via bulk-scan JSON escaping\n  |     +-- pre-encoded With() context (memcpy)\n  |     +-- typed fields (switch on FieldType, no reflection)\n  |\n  +-- output.Write(buf) (single syscall, no logger mutex)\n  |\n  +-- gohotpool.Put() (back to per-P cache)\n```\n \n## License\n \nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyk12397%2Fmach","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmyk12397%2Fmach","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmyk12397%2Fmach/lists"}