Skip to content

chore(build): reduce binary size by ~8 MB#362

Merged
Leeaandrob merged 3 commits intosipeed:mainfrom
blib:feat-bin-size
Feb 17, 2026
Merged

chore(build): reduce binary size by ~8 MB#362
Leeaandrob merged 3 commits intosipeed:mainfrom
blib:feat-bin-size

Conversation

@blib
Copy link
Contributor

@blib blib commented Feb 17, 2026

📝 Description

Reduce binary size by ~8 MB through two changes:

  1. Strip debug symbols — added -s -w to LDFLAGS (-s strips symbol table, -w strips DWARF debug info)
  2. Use stdlib JSON — added -tags stdjson to GOFLAGS so that telego uses encoding/json instead of the github.com/grbit/go-json dependency

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Linked Issue

#346

📚 Technical Context (Skip for Docs)

  • Reference: https://pkg.go.dev/cmd/link-s -w flags documentation; telego stdjson build tag
  • Reasoning: go-json adds ~1 MB to the binary and is only used by telego for marginal JSON performance gains. For an embedded/IoT target like PicoClaw, binary size matters more than JSON serialization speed. Stripping debug symbols is standard practice for release builds.

Signed-off-by: Boris Bliznioukov <blib@mail.com>
Copilot AI review requested due to automatic review settings February 17, 2026 13:33
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces binary size by approximately 8 MB through two build optimization techniques: stripping debug symbols with -s -w linker flags and using stdlib JSON instead of the heavier go-json dependency via the stdjson build tag. This is particularly valuable for the PicoClaw project's embedded/IoT target where binary size is more critical than marginal JSON performance gains.

Changes:

  • Added -s -w flags to LDFLAGS to strip symbol table and DWARF debug information
  • Added -tags stdjson to GOFLAGS to make the telego Telegram library use encoding/json instead of github.com/grbit/go-json

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

blib added 2 commits February 17, 2026 14:55
Signed-off-by: Boris Bliznioukov <blib@mail.com>
Signed-off-by: Boris Bliznioukov <blib@mail.com>
Copilot AI review requested due to automatic review settings February 17, 2026 14:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@Leeaandrob Leeaandrob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #362 Deep Review — @blib

Clean, well-documented build optimization. The ~8 MB reduction claim is confirmed locally: 25 MB → 17 MB (32% reduction).


Verification

  • Checked out branch locally: feat-bin-size
  • make build — succeeds, binary is 17 MB (vs 25 MB without PR)
  • file build/picoclaw-linux-amd64 — confirms stripped (symbols removed)
  • ./picoclaw version — version info correctly embedded (v0.1.2-9-g2d876ea, git: 2d876eaa, Build: ..., Go: go1.25.7)
  • go test ./... -tags stdjsonall tests passing across 14 packages
  • Verified goreleaser config: tags: [stdjson] + ldflags: [-s -w, ...] + version vars
  • Verified release workflow: id: setup-goGOVERSION env var → goreleaser template

Binary Size Breakdown

Build Size Delta
Without PR (upstream Makefile) 25 MB
With PR (-s -w + stdjson) 17 MB -8 MB (32%)

Summary of Findings

MEDIUM (Suggestion, not blocking)

  • M1: build-all target (Makefile:85-89) uses $(LDFLAGS) but NOT $(GOFLAGS) — cross-compiled binaries from make build-all will miss the stdjson tag (pre-existing issue, but now more impactful)

POSITIVE

  1. 32% binary size reduction confirmed — 25 MB → 17 MB
  2. Version info now in goreleaser builds{{ .Version }}, {{ .ShortCommit }}, {{ .Date }}, {{ .Env.GOVERSION }} were missing before this PR. This is a bonus improvement.
  3. stdjson is the official telego build tag — not a hack, properly supported by the library
  4. All tests pass with the stdjson tag — no functional regression
  5. -s -w is standard practice for Go release builds (Go linker docs, Docker best practices)
  6. Excellent PR description with references to Go linker docs and telego source

Verdict: APPROVE

Focused, low-risk build optimization with measurable impact. Ready to merge.

BUILD_TIME=$(shell date +%FT%T%z)
GO_VERSION=$(shell $(GO) version | awk '{print $$3}')
LDFLAGS=-ldflags "-X main.version=$(VERSION) -X main.gitCommit=$(GIT_COMMIT) -X main.buildTime=$(BUILD_TIME) -X main.goVersion=$(GO_VERSION)"
LDFLAGS=-ldflags "-X main.version=$(VERSION) -X main.gitCommit=$(GIT_COMMIT) -X main.buildTime=$(BUILD_TIME) -X main.goVersion=$(GO_VERSION) -s -w"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Positive] @blib — Clean addition of -s -w to LDFLAGS. The flags are placed after the -X version vars, which is correct (order does not matter for ldflags, but this reads naturally). Confirmed locally: file output shows stripped and picoclaw version still correctly reports version/commit/build info.

# Go variables
GO?=go
GOFLAGS?=-v
GOFLAGS?=-v -tags stdjson
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[M1 — MEDIUM: build-all misses GOFLAGS] @blib — The build target (line 77) uses both $(GOFLAGS) and $(LDFLAGS), but build-all (lines 85-89) only uses $(LDFLAGS):

# build (line 77) - correct:
$(GO) build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_PATH) ./$(CMD_DIR)

# build-all (line 85) - missing GOFLAGS:
GOOS=linux GOARCH=amd64 $(GO) build $(LDFLAGS) -o ... ./$(CMD_DIR)

This means make build-all cross-compiled binaries will NOT use stdjson, will include go-json, and will be ~1 MB larger per platform. This is a pre-existing inconsistency, but now that GOFLAGS carries the stdjson tag, it matters more.

Not blocking since goreleaser (used for actual releases) is correctly configured.

- -X main.version={{ .Version }}
- -X main.gitCommit={{ .ShortCommit }}
- -X main.buildTime={{ .Date }}
- -X main.goVersion={{ .Env.GOVERSION }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Positive — Bonus: Version Info in Release Builds] @blib — The goreleaser config previously had NO ldflags at all, meaning release binaries had empty version info (picoclaw version would show blank or default values). This PR adds both the size optimization AND the version embedding. Nice catch — this was a separate bug that got fixed as a side effect.

@Leeaandrob
Copy link
Collaborator

@blib take look

1 similar comment
@Leeaandrob
Copy link
Collaborator

@blib take look

@blib
Copy link
Contributor Author

blib commented Feb 17, 2026

Great!
biggest dependencies are github.com/openai/openai-go/v3 and github.com/anthropics/anthropic-sdk-go both of them because they both shim encoding/json from Go 1.24 which brings around 1Mb of code.
If we can make a requrements for Go version 1.24+ we can shave off another Mb or so.

┌────────────────────────────────────────────────────────────────────────────────┐
│ picoclaw-darwin-arm64                                                          │
├─────────┬─────────────────────────────────────────────────┬────────┬───────────┤
│ PERCENT │ NAME                                            │ SIZE   │ TYPE      │
├─────────┼─────────────────────────────────────────────────┼────────┼───────────┤
│ 17.28%  │ __rodata __DATA_CONST                           │ 2.9 MB │ section   │
│ 10.90%  │ github.com/openai/openai-go/v3                  │ 1.8 MB │ vendor    │
│ 7.20%   │ __rodata __TEXT                                 │ 1.2 MB │ section   │
│ 6.31%   │ net                                             │ 1.1 MB │ std       │
│ 6.21%   │ github.com/anthropics/anthropic-sdk-go          │ 1.0 MB │ vendor    │
│ 6.01%   │ crypto                                          │ 1.0 MB │ std       │
│ 4.56%   │ runtime                                         │ 762 kB │ std       │
│ 3.85%   │                                                 │ 643 kB │ generated │
│ 3.19%   │ github.com/sipeed/picoclaw                      │ 533 kB │ main      │
│ 2.91%   │ github.com/gogo/protobuf                        │ 486 kB │ vendor    │
│ 1.92%   │ github.com/bwmarrin/discordgo                   │ 320 kB │ vendor    │
│ 1.88%   │ __noptrdata __DATA                              │ 314 kB │ section   │
│ 1.17%   │ slices                                          │ 196 kB │ std       │
│ 1.16%   │ __gopclntab __DATA_CONST                        │ 193 kB │ section   │
│ 1.14%   │ github.com/valyala/fasthttp                     │ 190 kB │ vendor    │
│ 1.01%   │ reflect                                         │ 169 kB │ std       │
│ 0.98%   │ github.com/larksuite/oapi-sdk-go/v3             │ 163 kB │ vendor    │
│ 0.83%   │ math                                            │ 138 kB │ std       │
│ 0.80%   │ regexp                                          │ 133 kB │ std       │
│ 0.78%   │ encoding/json                                   │ 130 kB │ std       │
│ 0.66%   │ time                                            │ 109 kB │ std       │
│ 0.64%   │ os                                              │ 107 kB │ std       │
│ 0.63%   │ github.com/chzyer/readline                      │ 106 kB │ vendor    │
│ 0.63%   │ __data __DATA                                   │ 105 kB │ section   │
│ 0.61%   │ github.com/slack-go/slack                       │ 102 kB │ vendor    │

@Leeaandrob Leeaandrob merged commit 8807d82 into sipeed:main Feb 17, 2026
5 of 6 checks passed
@blib blib deleted the feat-bin-size branch February 17, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants