Skip to content
New issue

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

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

Already on GitHub? # to your account

feat: new polkadot wasm target and custom gc #22

Merged
merged 6 commits into from
Dec 6, 2023

Conversation

radkomih
Copy link
Collaborator

@radkomih radkomih commented Dec 1, 2023

Target 🎯

New polkawasm target, targeting standalone Wasm MVP (similar to Rust's wasm32-unknown-unknown), but also incorporating custom GC that utilizes an external allocator (as per Polkadot specification). Based on Tinygo 0.31.0 dev.

Wasm ⚙️

  • add custom Dockerfile and build script (with pre-build llvm)
  • add target implementation separate from the existing wasm/wasi
  • allow undefined (custom exported functions)
  • export globals and tables (__heap_base, __data_end)
  • import memory
  • change stack placement(no need, for now)
  • disable the scheduler (remove the support of goroutines and channels)
  • use wasi-libc with bulk memory ops disabled wasi-libc pr instead of providing own implementation. Not using -opt=0 drops the size significantly and improves the performance.
  • remove _start export (not supported from the host and not required with the custom extalloc gc)
  • remove wasm-libc exported allocation functions
  • lower away the sign extension operations --signext-lowering in wasm-opt

GC 🗑️

Custom implementation of a conservative, tracing (mark and sweep) garbage collector that relies on an external memory allocator (via ext_allocator_malloc, ext_allocator_free) for the WebAssembly (polkawasm) target. There is also a leaking GC implementation that only allocates memory through the external allocator but never frees it (not a real GC), however, it is useful for testing purposes and performance comparisons.

API

alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer

  • allocate memory with a requested size (invoke ext_allocator_malloc provided by the host)
  • keep track of each GC allocation in a separate global list (simplicity over performance)
  • resize/move the list when the capacity is reached (allocate new bigger list by invoking ext_allocator_malloc)

free(ptr unsafe.Pointer)

  • invoke ext_allocator_free provided by the host

GC()

  • scan from the roots (globals, stack) and mark all referenced allocations
  • free the unmarked allocations (update the allocations list and the total amount of memory)

🐛 fix _ExhaustsResourcesError tests:
order from size: requested allocation too large, requested 201326592, max possible allocations: 134217728.
Our goscale codec could be contributing to the problem by causing a lot of heap allocations.

Further Optimizations 🪛

  • size optimizations with wasm-opt
  • use wasi-libc memcpy
  • employ a more efficient data structure for keeping track of heap allocations (in terms of search/insertion/deletion operations)
  • add tests

Related Issues ⚠️

default gc - LimeChain/gosemble#96
scale/allocator bug - LimeChain/gosemble#134
fmt/allocator bug - LimeChain/gosemble#147
buffer bug - LimeChain/gosemble#148
refactored allocator - LimeChain/gosemble#285
new gc - LimeChain/gosemble#194

@radkomih radkomih self-assigned this Dec 1, 2023
Copy link

github-actions bot commented Dec 1, 2023

Size difference with the dev branch:

Binary size difference
 before   after   diff
  60960   60960      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
   9736    9736      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
  13268   13268      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/amg88xx
   8724    8724      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
  11612   11612      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go
   9784    9784      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
   8168    8168      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
   8344    8344      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
   7632    7632      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
  70492   70492      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pinetime     ./examples/bma42x/main.go
  63444   63444      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmi160/main.go
  27836   27836      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
  63544   63544      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp280/main.go
  12352   12352      0   0.00%  tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bmp388/main.go
   8128    8128      0   0.00%  tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
  22100   22100      0   0.00%  tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
  69332   69332      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
   4704    4704      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
  24932   24932      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espconsole/main.go
  25080   25080      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/esphub/main.go
  24932   24932      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espstation/main.go
  68844   68844      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/flash/console/spi
  64916   64916      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/flash/console/qspi
   7040    7040      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/gc9a01/main.go
  68148   68148      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
  68544   68544      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
   8372    8372      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/hcsr04/main.go
   5612    5612      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
   5656    5656      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/main.go
  10564   10564      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/hd44780i2c/main.go
  14516   14516      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/hts221/main.go
  16940   16940      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
  10052   10052      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic
  10832   10832      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/basic
  29052   29052      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/pyportal_boing
  10080   10080      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/scroll
  10908   10908      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/ili9341/scroll
 263564  263564      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/slideshow
  12052   12052      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
  13912   13912      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/lps22hb/main.go
  26124   26124      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/lsm303agr/main.go
  12520   12520      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
  10996   10996      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
  10176   10176      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017/main.go
  10604   10604      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp23017-multiple/main.go
   9816    9816      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
  66920   66920      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp2515/main.go
  22984   22984      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
  22936   22936      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit-v2 ./examples/microbitmatrix/main.go
   8444    8444      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
   8356    8356      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
  75196   75196      0   0.00%  tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go
  12148   12148      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go
   6080    6080      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
   5100    5100      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
   2681    2681      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino ./examples/servo
   7944    7944      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
  56608   56608      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
  56664   56664      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht4x/main.go
  56580   56580      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/shtc3/main.go
   6456    6456      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
   5960    5960      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
   5676    5676      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1331/main.go
   6376    6376      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7735/main.go
   6232    6232      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7789/main.go
  17156   17156      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/thermistor/main.go
  10312   10312      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-bluefruit ./examples/tone
  10096   10096      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/tm1637/main.go
   9404    9404      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/fourwire/main.go
  12468   12468      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/pyportal_touchpaint/main.go
  15804   15804      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
  13848   13848      0   0.00%  tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl6180x/main.go
   6452    6452      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
   6004    6004      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
   6260    6260      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd4in2/main.go
 137504  137504      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/ntpclient/main.go
 137512  137512      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/udpstation/main.go
 137496  137496      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/tcpclient/main.go
 137792  137792      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/webclient/main.go
   6924    6924      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
   5526    5526      0   0.00%  tinygo build -size short -o ./build/test.bin -target=m5stamp-c3          ./examples/ws2812
  61872   61872      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-nrf52840 ./examples/is31fl3731/main.go
   1549    1549      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino   ./examples/ws2812
    880     880      0   0.00%  tinygo build -size short -o ./build/test.hex -target=digispark ./examples/ws2812
  32248   32248      0   0.00%  tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bme280/main.go
  16612   16612      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/microphone/main.go
  11268   11268      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/buzzer/main.go
  12976   12976      0   0.00%  tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/veml6070/main.go
   6800    6800      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/simple/main.go
   8720    8720      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/speed/main.go
   6764    6764      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/simple/main.go
   9336    9336      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/speed/main.go
   7304    7304      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nucleo-f103rb ./examples/shiftregister/main.go
   6932    6932      0   0.00%  tinygo build -size short -o ./build/test.hex -target=hifive1b ./examples/ssd1351/main.go
  13172   13172      0   0.00%  tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis2mdl/main.go
   8428    8428      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/max72xx/main.go
  77152   77152      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go
  36608   36608      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-rp2040 ./examples/pcf8523/
  71136   71136      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/alarm/
   7400    7400      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/clkout/
  70768   70768      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/time/
  71056   71056      0   0.00%  tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
  12076   12076      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pico ./examples/qmi8658c/main.go
   8996    8996      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
   9280    9280      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nucleo-l432kc ./examples/aht20/main.go
  72288   72288      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/sdcard/console/
  82580   82580      0   0.00%  tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webclient/
  71996   71996      0   0.00%  tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/webserver/
  98644   98644      0   0.00%  tinygo build -size short -o ./build/test.hex -target=wioterminal ./examples/rtl8720dn/mqttsub/
  60756   60756      0   0.00%  tinygo build -size short -o ./build/test.hex -target=feather-m4 ./examples/i2csoft/adt7410/
  10152   10152      0   0.00%  tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
   8916    8916      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
  14564   14564      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/sx126x/lora_rxtx/
  26260   26260      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/ssd1289/main.go
  11188   11188      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pico ./examples/irremote/main.go
  11204   11204      0   0.00%  tinygo build -size short -o ./build/test.hex -target=badger2040 ./examples/uc8151/main.go
  10312   10312      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/scd4x/main.go
   8692    8692      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
   9576    9576      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ds18b20/main.go
  81312   81312      0   0.00%  tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
  15732   15732      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go
   9800    9800      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu6886/main.go
   7840    7840      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ttp229/main.go
  66056   66056      0   0.00%  tinygo build -size short -o ./build/test.hex -target=pico ./examples/ndir/main_ndir.go
  61368   61368      0   0.00%  tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ndir/main_ndir.go
  64616   64616      0   0.00%  tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ndir/main_ndir.go
   9216    9216      0   0.00%  tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/mpu9150/main.go
3827244 3827244      0   0.00%   sum

polkawasm.sh Outdated Show resolved Hide resolved
src/runtime/panic.go Outdated Show resolved Hide resolved
src/runtime/arch_tinygowasm.go Outdated Show resolved Hide resolved
src/runtime/gc_extalloc.go Outdated Show resolved Hide resolved
src/runtime/gc_extalloc.go Outdated Show resolved Hide resolved
compileopts/config.go Outdated Show resolved Hide resolved
compileopts/options.go Outdated Show resolved Hide resolved
main.go Outdated Show resolved Hide resolved
@radkomih radkomih requested a review from failfmi December 5, 2023 14:25
@radkomih radkomih force-pushed the feat-polkadot-wasm-target-and-gc branch from 3270b64 to 7bab5e1 Compare December 6, 2023 07:23
@radkomih radkomih requested a review from failfmi December 6, 2023 07:27
@radkomih radkomih merged commit 68308aa into polkawasm-target-dev Dec 6, 2023
8 of 10 checks passed
radkomih added a commit that referenced this pull request Jan 23, 2024
* polkawasm: add dockerfile and build script
* polkawasm: add new target separate from the existing wasm/wasi
* polkawasm: import memory, allow undefined, export globals and tables, disable scheduler, specify gc
* polkawasm: switch wasi-libc and wasm-opt to MVP instructions set
* polkawasm: remove _start export. remove wasm-libc allocation functions
* polkawasm: add custom gc that relies on an external allocator
radkomih added a commit that referenced this pull request Apr 1, 2024
* polkawasm: add dockerfile and build script
* polkawasm: add new target separate from the existing wasm/wasi
* polkawasm: import memory, allow undefined, export globals and tables, disable scheduler, specify gc
* polkawasm: switch wasi-libc and wasm-opt to MVP instructions set
* polkawasm: remove _start export. remove wasm-libc allocation functions
* polkawasm: add custom gc that relies on an external allocator
radkomih added a commit that referenced this pull request May 31, 2024
* polkawasm: add dockerfile and build script
* polkawasm: add new target separate from the existing wasm/wasi
* polkawasm: import memory, allow undefined, export globals and tables, disable scheduler, specify gc
* polkawasm: switch wasi-libc and wasm-opt to MVP instructions set
* polkawasm: remove _start export. remove wasm-libc allocation functions
* polkawasm: add custom gc that relies on an external allocator
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants