Skip to content

Tags: xtaci/gaio

Tags

v1.2.34

Toggle v1.2.34's commit message
feat: add Windows support using WSAPoll

This commit adds Windows platform support to gaio using WSAPoll-based
I/O multiplexing (Reactor pattern).

Changes:
- Add aio_windows.go: WSAPoll-based poller implementation
  - Socket pair for wakeup mechanism (loopback TCP connection)
  - WSARecv/WSASend for non-blocking I/O
  - WSADuplicateSocketW/WSASocketW for socket duplication
  - Proper socket closure using closesocket()

- Add affinity_windows.go: CPU affinity using SetThreadAffinityMask

- Add aio_unix.go: Extract Unix-specific dupconn() and closeFd()

- Update aio_test.go: Skip high-concurrency tests (8k+ connections) on
  Windows due to system ephemeral port limits

Tested on:
- Linux: All tests pass
- Windows: All tests pass (high-concurrency tests skipped)

v1.2.33

Toggle v1.2.33's commit message
refactor: replace unsafe interface pointer access with reflect.ValueO…

…f().Pointer()

Replace the unsafe pointer manipulation for extracting data pointer from
net.Conn interface with reflect.ValueOf().Pointer() for better
forward compatibility.

The previous implementation relied on Go's internal interface memory
layout (type, data), which is an implementation detail not covered by
Go 1 compatibility guarantee. The new approach uses the public reflect
API which is officially supported and stable.

Changes:
- Remove "unsafe" package import, add "reflect" package
- Update aioCreate() to use reflect for getting connection pointer
- Update handleGC() to use reflect for getting connection pointer

The performance impact is negligible since:
- Pointer extraction only happens once per connection registration
- Reflect overhead is nanoseconds vs network I/O latency (microseconds)

All tests pass including race detection.

v1.2.32

Toggle v1.2.32's commit message
fix: critical bug in interface pointer extraction for GC tracking

The previous implementation incorrectly extracted the type pointer (first word)
from Go interfaces instead of the data pointer (second word). Since all
*net.TCPConn share the same type pointer, this caused:

1. All connections to be identified by the same pointer value
2. Only the first connection to be properly registered in the watcher
3. Finalizers not being set correctly for subsequent connections
4. GC-based cleanup to fail (only 1 connection cleaned up instead of all)

Root cause:
  Go interfaces are laid out as [type_ptr, data_ptr] (two machine words).
  The old code: `ptr := *(*uintptr)(unsafe.Pointer(&conn))`
  only retrieved the type pointer, which is identical for all *net.TCPConn.

Fix:
  Changed to extract the second word (data pointer) which uniquely identifies
  each connection instance:

        iface := ([2]uintptr)(unsafe.Pointer(&conn))
        ptr := iface[1] // data pointer

Affected functions:
- aioCreate(): connection registration and finalizer setup
- handleGC(): garbage collection callback handling

Also includes:
- Modernize codebase for Go 1.21+ (interface{} → any, clear() builtin)
- Use sync.Pool inline initialization
- Improve mutex handling with defer patterns
- Enhanced TestGC with 200 connections (requires ≥100 successful GC)

All tests pass with race detector enabled.

v1.2.31

Toggle v1.2.31's commit message
perf: eliminate allocations in WaitIO hot path

- Add pre-allocated results slice to watcher struct to reuse across
  WaitIO calls, reducing GC pressure in high-throughput scenarios
- Replace reflect.ValueOf().Pointer() with unsafe pointer extraction
  in aioCreate() and handleGC() for faster pointer retrieval
- Remove reflect package import as it's no longer needed

Benchmark results (BenchmarkEcho1K):
  Before: 478 B/op, 4 allocs/op
  After:  0 B/op, 0 allocs/op

Memory profile shows WaitIO allocation dropped from 60.51MB to 0MB,
which is critical for C10K+ concurrent connection scenarios.

v1.2.30

Toggle v1.2.30's commit message
refine comments

v1.2.29

Toggle v1.2.29's commit message
fix: bug fixes and performance optimizations

Bug fixes:
- Fix eventfd error handling: return actual syscall error instead of nil
- Fix rawRead/rawWrite return value handling on error (-1 case)
- Fix timer initialization: stop immediately after creation to avoid spurious timeout
- Fix timeout heap cleanup: properly remove entries in deliver()

Performance optimizations:
- Pre-allocate maps (descs, connIdents) with initial capacity for C10K scenarios
- Pre-allocate slices (pendingCreate, pendingProcessing, recycles, eventSet)
- Add fdDescPool to reuse fdDesc objects and reduce allocations
- Optimize handleEvents: use index-based loop and early length check
- Optimize reflect usage: remove redundant TypeOf() call in aioCreate
- Pre-allocate kqueue changes slice on BSD

v1.2.28

Toggle v1.2.28's commit message
Fix: whenever a request is pushed onto w.timeouts, compare it with th…

…e current minimum and reset the timer if the newcomer expires sooner.

Fix: only close the user connection after Watch succeeds, and ensure the duplicated FD is closed on every error path.
Fix: Negative CPU IDs panic

v1.2.27

Toggle v1.2.27's commit message
use channel to notify buffer swap to create a full memory barrier, wh…

…ile atomic cannot

v1.2.26

Toggle v1.2.26's commit message
same with previous commit

v1.2.25

Toggle v1.2.25's commit message
to prevent allocation of the same address for net.Conn