[PR #152] feat: make PreallocatedBuffersPerPool configurable at runtime #170

Open
opened 2026-10-13 21:04:14 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amneziawg-go/pull/152
Author: @william-aqn
Created: 7/12/2026
Status: 🔄 Open

Base: master ← Head: configurable-buffer-pool


📝 Commits (1)

  • f46f3d2 feat: make PreallocatedBuffersPerPool configurable at runtime

📊 Changes

5 files changed (+50 additions, -21 deletions)

View changed files

📝 README.md (+2 -0)
📝 device/queueconstants_android.go (+9 -6)
📝 device/queueconstants_default.go (+12 -6)
📝 device/queueconstants_windows.go (+10 -6)
📝 main.go (+17 -3)

📄 Description

On memory-constrained hosts (consumer routers with 256-512 MB of RAM) the Linux default of PreallocatedBuffersPerPool = 0 lets the receive path allocate 64 KiB message buffers without bound whenever sustained inbound traffic outpaces the (software) crypto pipeline. Field case: an ASUS RT-AX82U (512 MB, armv7) running the standalone daemon dies with fatal error: runtime: out of memory a few minutes into any sustained stream, allocation stack in
RoutineReceiveIncoming -> GetMessageBuffer -> WaitPool.Get. Rebuilding with the pool bounded at 1024 (the value the ios profile already ships) fixes it: WaitPool.Get blocks the receiver when the pool is full, the kernel drops excess UDP, and peers treat that as ordinary congestion.

Make the bound adjustable without patching the source:

  • turn PreallocatedBuffersPerPool into a typed var on the default, android and windows profiles; ios already declares it as a var for exactly this reason. Platform defaults are unchanged.
  • the standalone daemon reads WG_PREALLOCATED_BUFFERS_PER_POOL from the environment (same configuration surface as LOG_LEVEL and WG_PROCESS_FOREGROUND) before creating the device; unset keeps the platform default, 0 means unbounded, and a non-numeric value fails startup with a clear error.
  • embedders using the device package directly can assign device.PreallocatedBuffersPerPool before calling NewDevice.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amneziawg-go/pull/152 **Author:** [@william-aqn](https://github.com/william-aqn) **Created:** 7/12/2026 **Status:** 🔄 Open **Base:** `master` ← **Head:** `configurable-buffer-pool` --- ### 📝 Commits (1) - [`f46f3d2`](https://github.com/amnezia-vpn/amneziawg-go/commit/f46f3d2b088eace5a2526f366c597788a6dcdb08) feat: make PreallocatedBuffersPerPool configurable at runtime ### 📊 Changes **5 files changed** (+50 additions, -21 deletions) <details> <summary>View changed files</summary> 📝 `README.md` (+2 -0) 📝 `device/queueconstants_android.go` (+9 -6) 📝 `device/queueconstants_default.go` (+12 -6) 📝 `device/queueconstants_windows.go` (+10 -6) 📝 `main.go` (+17 -3) </details> ### 📄 Description On memory-constrained hosts (consumer routers with 256-512 MB of RAM) the Linux default of PreallocatedBuffersPerPool = 0 lets the receive path allocate 64 KiB message buffers without bound whenever sustained inbound traffic outpaces the (software) crypto pipeline. Field case: an ASUS RT-AX82U (512 MB, armv7) running the standalone daemon dies with `fatal error: runtime: out of memory` a few minutes into any sustained stream, allocation stack in RoutineReceiveIncoming -> GetMessageBuffer -> WaitPool.Get. Rebuilding with the pool bounded at 1024 (the value the ios profile already ships) fixes it: WaitPool.Get blocks the receiver when the pool is full, the kernel drops excess UDP, and peers treat that as ordinary congestion. Make the bound adjustable without patching the source: - turn PreallocatedBuffersPerPool into a typed var on the default, android and windows profiles; ios already declares it as a var for exactly this reason. Platform defaults are unchanged. - the standalone daemon reads WG_PREALLOCATED_BUFFERS_PER_POOL from the environment (same configuration surface as LOG_LEVEL and WG_PROCESS_FOREGROUND) before creating the device; unset keeps the platform default, 0 means unbounded, and a non-numeric value fails startup with a clear error. - embedders using the device package directly can assign device.PreallocatedBuffersPerPool before calling NewDevice. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amneziawg-go#170
No description provided.