Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to disable output entirely #721

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aykevl
Copy link

@aykevl aykevl commented Mar 26, 2025

This is mostly useful in environments where printf adds a non-negligible amount of code (for example, WebAssembly in the browser). Disabling all output shrinks the binary. Of course, this option should not be used when testing/debugging the GC.

I didn't test the binary size difference on WebAssembly, but on Linux (arm64) with a statically linked musl libc the difference is 20kB in my setup.

This is mostly useful in environments where printf adds a non-negligible
amount of code (for example, WebAssembly in the browser). Disabling all
output shrinks the binary. Of course, this option should not be used
when testing/debugging the GC.

I didn't test the binary size difference on WebAssembly, but on Linux
(arm64) with a statically linked musl libc the difference is 20kB in my
setup.
@ivmai
Copy link
Owner

ivmai commented Mar 26, 2025

Okay!

@ivmai
Copy link
Owner

ivmai commented Mar 26, 2025

BTW. Could you please reference your project where the feature is needed?

@aykevl
Copy link
Author

aykevl commented Mar 26, 2025

I'm using this library in TinyGo. Right now we only use bdwgc on Linux, MacOS, and Windows (where binary size doesn't matter a lot), but I'm working on WebAssembly support. For WebAssembly I'd like to keep binary size down as much as possible.

See: tinygo-org/tinygo#4812

@aykevl
Copy link
Author

aykevl commented Mar 26, 2025

Maybe this library could even be used baremetal? That would be interesting to investigate. Our own GC is kinda slow. For baremetal (microcontrollers mostly), binary size matters even more.

@ivmai
Copy link
Owner

ivmai commented Mar 26, 2025

Maybe this library could even be used baremetal? That would be interesting to investigate. Our own GC is kinda slow. For baremetal (microcontrollers mostly), binary size matters even more.

Yes, it should be possible, but I've not heard of such experiments. See NOSYS macro.
Related open issue: #393

@ivmai
Copy link
Owner

ivmai commented Mar 28, 2025

I'm using this library in TinyGo. Right now we only use bdwgc on Linux, MacOS, and Windows (where binary size doesn't matter a lot), but I'm working on WebAssembly support. For WebAssembly I'd like to keep binary size down as much as possible.

Off-topic: BTW, ages ago my record was a 55KB Win23 executable containing a GC java benchmark (GCBench) compiled to native code, java runtime and bdwgc.

@ivmai
Copy link
Owner

ivmai commented Mar 28, 2025

Note: I've tried to produce a minimal statically-linked executable w/o proposed patch:

See the experiment results in #722

@ivmai
Copy link
Owner

ivmai commented Mar 28, 2025

Somewhat related issue: #568

@aykevl
Copy link
Author

aykevl commented Mar 29, 2025

Maybe this library could even be used baremetal? That would be interesting to investigate. Our own GC is kinda slow. For baremetal (microcontrollers mostly), binary size matters even more.

Yes, it should be possible, but I've not heard of such experiments. See NOSYS macro.
Related open issue: #393

Ah, cool, thank you! Will look into NOSYS when I get around to it.

@aykevl
Copy link
Author

aykevl commented Mar 29, 2025

Off-topic: BTW, ages ago my record was a 55KB Win23 executable containing a GC java benchmark (GCBench) compiled to native code, java runtime and bdwgc.

Right now in TinyGo (with this patch included), I've got a binary of 39kB on linux/arm64:

$ tinygo build -o test ./testdata/gc.go
$ strip test
$ ls -l test
.rwxr-xr-x@ 39k ayke 29 mrt 09:24 test

This is a small and (overly) simple test to see whether the GC is working at all and not overwriting memory.

@aykevl
Copy link
Author

aykevl commented Mar 29, 2025

To be clear, the goal of this patch is to avoid linking in the vsnprintf function which is rather large. TinyGo binaries do not normally call printf-like functions, Go has its own formatting code. The code size savings of bdwgc itself are small in comparson.

Before:

   code  rodata    data     bss |   flash     ram | package
------------------------------- | --------------- | -------
      0       0       0       7 |       0       7 | (padding)
    844    6968     340    4132 |    8152    4472 | (unknown)
  21716    2135     876  118147 |   24727  119023 | C bdwgc
   2900       0       0       0 |    2900       0 | C compiler-rt
  12992    2729       4     568 |   15725     572 | C musl
      0      32       0       0 |      32       0 | Go types
    436      24       0      16 |     460      16 | internal/task
    252      41       4     112 |     297     116 | main
   1532     217       0      18 |    1749      18 | runtime
------------------------------- | --------------- | -------
  40672   12146    1224  123000 |   54042  124224 | total

After:

   code  rodata    data     bss |   flash     ram | package
------------------------------- | --------------- | -------
      0       0       0       7 |       0       7 | (padding)
    628    5262     344    4308 |    6234    4652 | (unknown)
  21288    2039     872  118147 |   24199  119019 | C bdwgc
   4476      27       4     568 |    4507     572 | C musl
      0      32       0       0 |      32       0 | Go types
    436      24       0      16 |     460      16 | internal/task
    252      41       4     112 |     297     116 | main
   1532     217       0      18 |    1749      18 | runtime
------------------------------- | --------------- | -------
  28612    7642    1224  123176 |   37478  124400 | total

(The output is a bit weird and designed for MCU usage, "flash" basically means binary size and "ram" means static data like non-constant globals).

The bdwgc library goes from 24727 to 24199 bytes, a difference of half a kilobyte. That's not very large. However, the musl libc (which is statically linked) goes from 15725 to 4507 - around 10kB reduction. And not everything is accounted for: (unknown) also reduces a bit (the binary size attribution code isn't perfect, it bases itself on DWARF data and other things after linking so can't always correctly attribute where some binary data originally comes from).

WebAssembly will be different, but since we also use a statically linked binary on WebAssembly, I expect a similar binary size reduction.

(I also see that compiler-rt is ~3kB with vsnprintf linked in, that's all due to 128-bit float support and won't apply to WebAssembly).

@ivmai
Copy link
Owner

ivmai commented Mar 31, 2025

Got it, now it is more clear.
I will process the patch this week.

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