A thread-safe queue faster and more resource efficient than golang's native channels
MIT License
Add compatibility with go 1.22
https://github.com/alphadose/ZenQ/pull/17 @Aoang
Published by alphadose 9 months ago
Add Size()
function which returns the number of items in the queue at any given time
Published by alphadose almost 2 years ago
Add support for ppc64 and s390x CPU architectures
Published by alphadose about 2 years ago
Fix the assembly code in asm_arm.s
and measure ZenQ's performance against channels for a low-end device (32 bit raspberry pi)
Device Info
`.::///+:/-. --///+//-:`` alphadose@neverwinter
`+oooooooooooo: `+oooooooooooo: -------------------
/oooo++//ooooo: ooooo+//+ooooo. OS: Raspbian GNU/Linux 11 (bullseye) armv7l
`+ooooooo:-:oo- +o+::/ooooooo: Host: Raspberry Pi 4 Model B Rev 1.5
`:oooooooo+`` `.oooooooo+- Kernel: 5.15.32-v7l+
`:++ooo/. :+ooo+/.` Uptime: 1 hour, 58 mins
...` `.----.` ``.. Packages: 569 (dpkg)
.::::-``:::::::::.`-:::-` Shell: bash 5.1.4
-:::-` .:::::::-` `-:::- Terminal: /dev/pts/0
`::. `.--.` `` `.---.``.::` CPU: BCM2711 (4) @ 1.800GHz
.::::::::` -::::::::` ` Memory: 68MiB / 3838MiB
.::` .:::::::::- `::::::::::``::.
-:::` ::::::::::. ::::::::::.`:::-
:::: -::::::::. `-:::::::: ::::
-::- .-:::-.``....``.-::-. -::-
.. `` .::::::::. `..`..
-:::-` -::::::::::` .:::::`
:::::::` -::::::::::` :::::::.
.::::::: -::::::::. ::::::::
`-:::::` ..--.` ::::::.
`...` `...--..` `...`
.::::::::::
`.-::::-`
Benchstat of 20 runs
goos: linux
goarch: arm
name time/op
_Chan_NumWriters1_InputSize600-4 230µs ± 4%
_ZenQ_NumWriters1_InputSize600-4 186µs ± 5%
_Chan_NumWriters3_InputSize60000-4 28.2ms ± 3%
_ZenQ_NumWriters3_InputSize60000-4 12.8ms ± 0%
_Chan_NumWriters8_InputSize6000000-4 4.14s ±10%
_ZenQ_NumWriters8_InputSize6000000-4 1.32s ± 1%
_Chan_NumWriters100_InputSize6000000-4 5.97s ± 5%
_ZenQ_NumWriters100_InputSize6000000-4 1.48s ± 5%
_Chan_NumWriters1000_InputSize7000000-4 7.23s ± 6%
_ZenQ_NumWriters1000_InputSize7000000-4 2.09s ± 4%
_Chan_Million_Blocking_Writers-4 20.3s ± 2%
_ZenQ_Million_Blocking_Writers-4 6.96s ± 4%
name alloc/op
_Chan_NumWriters1_InputSize600-4 0.00B
_ZenQ_NumWriters1_InputSize600-4 0.00B
_Chan_NumWriters3_InputSize60000-4 227B ±27%
_ZenQ_NumWriters3_InputSize60000-4 77.9B ±91%
_Chan_NumWriters8_InputSize6000000-4 499B ±189%
_ZenQ_NumWriters8_InputSize6000000-4 1.49kB ± 4%
_Chan_NumWriters100_InputSize6000000-4 27.5kB ±19%
_ZenQ_NumWriters100_InputSize6000000-4 27.7kB ±42%
_Chan_NumWriters1000_InputSize7000000-4 290kB ± 5%
_ZenQ_NumWriters1000_InputSize7000000-4 135kB ± 8%
_Chan_Million_Blocking_Writers-4 325MB ± 0%
_ZenQ_Million_Blocking_Writers-4 76.2MB ± 3%
name allocs/op
_Chan_NumWriters1_InputSize600-4 0.00
_ZenQ_NumWriters1_InputSize600-4 0.00
_Chan_NumWriters3_InputSize60000-4 1.00 ± 0%
_ZenQ_NumWriters3_InputSize60000-4 0.00
_Chan_NumWriters8_InputSize6000000-4 4.30 ±109%
_ZenQ_NumWriters8_InputSize6000000-4 19.2 ± 9%
_Chan_NumWriters100_InputSize6000000-4 171 ±13%
_ZenQ_NumWriters100_InputSize6000000-4 194 ±25%
_Chan_NumWriters1000_InputSize7000000-4 1.84k ± 3%
_ZenQ_NumWriters1000_InputSize7000000-4 1.09k ± 4%
_Chan_Million_Blocking_Writers-4 2.00M ± 0%
_ZenQ_Million_Blocking_Writers-4 1.00M ± 0%
Conclusion -> ZenQ scales better even in low-end devices
Published by alphadose about 2 years ago
Published by alphadose about 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Improve the performance of select by adding direct_send and optimistic first pass read approach
ZenQ Select() is now comparable to channels although not as fast for large batch sizes
To improve ZenQ's selection performance even beyond this, the goroutine pointer itself has to be mutated for even faster data transfer during selections
With Input Batch Size: 60 and Num Concurrent Writers: 4
Chan Select Runner completed transfer in: 55.375µs
ZenQ Select Runner completed transfer in: 56.125µs
====================================================================
With Input Batch Size: 600 and Num Concurrent Writers: 4
Chan Select Runner completed transfer in: 181.334µs
ZenQ Select Runner completed transfer in: 432.75µs
====================================================================
With Input Batch Size: 6000 and Num Concurrent Writers: 4
Chan Select Runner completed transfer in: 936.042µs
ZenQ Select Runner completed transfer in: 4.410916ms
====================================================================
With Input Batch Size: 600000 and Num Concurrent Writers: 4
Chan Select Runner completed transfer in: 140.836375ms
ZenQ Select Runner completed transfer in: 380.546875ms
====================================================================
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
name old time/op new time/op delta
_ZenQ_NumWriters1_InputSize600-8 16.5µs ± 1% 17.9µs ± 1% +8.65% (p=0.000 n=28+29)
_ZenQ_NumWriters3_InputSize60000-8 2.85ms ± 0% 2.67ms ± 6% -6.11% (p=0.000 n=23+30)
_ZenQ_NumWriters8_InputSize6000000-8 417ms ± 0% 313ms ± 5% -24.83% (p=0.000 n=23+29)
_ZenQ_NumWriters100_InputSize6000000-8 741ms ± 3% 516ms ± 2% -30.40% (p=0.000 n=29+30)
_ZenQ_NumWriters1000_InputSize7000000-8 1.05s ± 1% 0.45s ± 9% -57.58% (p=0.000 n=28+30)
_ZenQ_Million_Blocking_Writers-8 7.01s ±44% 10.98s ± 4% +56.54% (p=0.000 n=30+28)
name old alloc/op new alloc/op delta
_ZenQ_NumWriters1_InputSize600-8 0.00B 0.00B ~ (all equal)
_ZenQ_NumWriters3_InputSize60000-8 28.9B ±111% 34.8B ±127% ~ (p=0.268 n=30+29)
_ZenQ_NumWriters8_InputSize6000000-8 885B ±163% 671B ±222% ~ (p=0.208 n=30+30)
_ZenQ_NumWriters100_InputSize6000000-8 16.2kB ±66% 13.3kB ±100% ~ (p=0.072 n=30+30)
_ZenQ_NumWriters1000_InputSize7000000-8 62.4kB ±82% 2.4kB ±210% -96.20% (p=0.000 n=30+30)
_ZenQ_Million_Blocking_Writers-8 95.9MB ± 0% 95.5MB ± 0% -0.41% (p=0.000 n=28+30)
name old allocs/op new allocs/op delta
_ZenQ_NumWriters1_InputSize600-8 0.00 0.00 ~ (all equal)
_ZenQ_NumWriters3_InputSize60000-8 0.00 0.00 ~ (all equal)
_ZenQ_NumWriters8_InputSize6000000-8 2.07 ±142% 1.40 ±186% ~ (p=0.081 n=30+30)
_ZenQ_NumWriters100_InputSize6000000-8 53.5 ±50% 31.8 ±100% -40.60% (p=0.000 n=30+30)
_ZenQ_NumWriters1000_InputSize7000000-8 525 ±39% 6 ±227% -98.95% (p=0.000 n=30+30)
_ZenQ_Million_Blocking_Writers-8 1.00M ± 0% 0.99M ± 0% -0.41% (p=0.000 n=28+29)
Published by alphadose over 2 years ago
Published by alphadose over 2 years ago
In previous version of ZenQ, the tests timed out in cases of a million number of goroutines but this is handled in this version by parking extra goroutines
name old time/op new time/op delta
_Chan_NumWriters1_InputSize600-8 23.2µs ± 0% 24.2µs ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters1_InputSize600-8 16.3µs ± 0% 16.7µs ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters3_InputSize60000-8 5.55ms ± 0% 6.19ms ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters3_InputSize60000-8 2.80ms ± 0% 2.85ms ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters8_InputSize6000000-8 694ms ± 0% 730ms ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters8_InputSize6000000-8 446ms ± 0% 421ms ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters100_InputSize6000000-8 1.59s ± 0% 1.60s ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters100_InputSize6000000-8 490ms ± 0% 736ms ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters1000_InputSize7000000-8 1.97s ± 0% 1.97s ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters1000_InputSize7000000-8 769ms ± 0% 1052ms ± 0% ~ (p=1.000 n=1+1)
name old alloc/op new alloc/op delta
_Chan_NumWriters1_InputSize600-8 0.00B 0.00B ~ (all equal)
_ZenQ_NumWriters1_InputSize600-8 0.00B 0.00B ~ (all equal)
_Chan_NumWriters3_InputSize60000-8 63.0B ± 0% 96.0B ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters3_InputSize60000-8 44.0B ± 0% 0.0B ~ (p=1.000 n=1+1)
_Chan_NumWriters8_InputSize6000000-8 1.76kB ± 0% 0.24kB ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters8_InputSize6000000-8 1.52kB ± 0% 0.31kB ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters100_InputSize6000000-8 51.2kB ± 0% 35.9kB ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters100_InputSize6000000-8 5.27kB ± 0% 18.94kB ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters1000_InputSize7000000-8 492kB ± 0% 492kB ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters1000_InputSize7000000-8 16.6kB ± 0% 34.3kB ± 0% ~ (p=1.000 n=1+1)
name old allocs/op new allocs/op delta
_Chan_NumWriters1_InputSize600-8 0.00 0.00 ~ (all equal)
_ZenQ_NumWriters1_InputSize600-8 0.00 0.00 ~ (all equal)
_Chan_NumWriters3_InputSize60000-8 0.00 0.00 ~ (all equal)
_ZenQ_NumWriters3_InputSize60000-8 0.00 0.00 ~ (all equal)
_Chan_NumWriters8_InputSize6000000-8 5.00 ± 0% 2.00 ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters8_InputSize6000000-8 3.00 ± 0% 1.00 ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters100_InputSize6000000-8 163 ± 0% 147 ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters100_InputSize6000000-8 12.0 ± 0% 49.0 ± 0% ~ (p=1.000 n=1+1)
_Chan_NumWriters1000_InputSize7000000-8 1.81k ± 0% 1.77k ± 0% ~ (p=1.000 n=1+1)
_ZenQ_NumWriters1000_InputSize7000000-8 40.0 ± 0% 357.0 ± 0% ~ (p=1.000 n=1+1)