From 86bc0c61fbfd8e77c0b27d3cfb87cba9522cda71 Mon Sep 17 00:00:00 2001 From: leo-gan Date: Tue, 1 Sep 2026 15:23:50 -0700 Subject: [PATCH 1/5] feat(experiments): add payload-size sweep across 5 languages SPSC ranking is a size question, not a named data-type question. Sweep 1 B / 64 B / 256 B / 4 KiB / 64 KiB at n=100 with full reps. Finding: default matrix needs 256 B and 4 KiB; 64 KiB is research-only. --- analysis/tests/test_run_config_v2.py | 20 +- .../experiments/13-payload-size-sweep.json.gz | Bin 0 -> 8511 bytes dashboard/public/data/experiments/index.json | 55 +- docs/analysis/test_data_configuration.md | 8 +- experiments/13-payload-size-sweep/README.md | 21 + .../13-payload-size-sweep/c/results.json | 463 +++ .../13-payload-size-sweep/c/results.md | 61 + .../13-payload-size-sweep/csharp/results.json | 556 +++ .../13-payload-size-sweep/csharp/results.md | 65 + .../13-payload-size-sweep/experiment.yaml | 92 + .../javascript/results.json | 659 ++++ .../javascript/results.md | 72 + .../13-payload-size-sweep/python/results.json | 744 ++++ .../13-payload-size-sweep/python/results.md | 74 + .../13-payload-size-sweep/results.json | 3268 +++++++++++++++++ experiments/13-payload-size-sweep/results.md | 91 + experiments/13-payload-size-sweep/run.sh | 32 + experiments/13-payload-size-sweep/run.yaml | 20 + .../13-payload-size-sweep/rust/results.json | 767 ++++ .../13-payload-size-sweep/rust/results.md | 77 + experiments/13-payload-size-sweep/sample.json | 7 + .../13-payload-size-sweep/summarize.py | 492 +++ experiments/PLAN.md | 27 + experiments/README.md | 1 + schemas/data_catalog_v2.yaml | 33 + 25 files changed, 7699 insertions(+), 6 deletions(-) create mode 100644 dashboard/public/data/experiments/13-payload-size-sweep.json.gz create mode 100644 experiments/13-payload-size-sweep/README.md create mode 100644 experiments/13-payload-size-sweep/c/results.json create mode 100644 experiments/13-payload-size-sweep/c/results.md create mode 100644 experiments/13-payload-size-sweep/csharp/results.json create mode 100644 experiments/13-payload-size-sweep/csharp/results.md create mode 100644 experiments/13-payload-size-sweep/experiment.yaml create mode 100644 experiments/13-payload-size-sweep/javascript/results.json create mode 100644 experiments/13-payload-size-sweep/javascript/results.md create mode 100644 experiments/13-payload-size-sweep/python/results.json create mode 100644 experiments/13-payload-size-sweep/python/results.md create mode 100644 experiments/13-payload-size-sweep/results.json create mode 100644 experiments/13-payload-size-sweep/results.md create mode 100755 experiments/13-payload-size-sweep/run.sh create mode 100644 experiments/13-payload-size-sweep/run.yaml create mode 100644 experiments/13-payload-size-sweep/rust/results.json create mode 100644 experiments/13-payload-size-sweep/rust/results.md create mode 100644 experiments/13-payload-size-sweep/sample.json create mode 100755 experiments/13-payload-size-sweep/summarize.py diff --git a/analysis/tests/test_run_config_v2.py b/analysis/tests/test_run_config_v2.py index a19867f..cc06f12 100644 --- a/analysis/tests/test_run_config_v2.py +++ b/analysis/tests/test_run_config_v2.py @@ -21,10 +21,28 @@ _CATALOG = _REPO / "schemas" / "data_catalog_v2.yaml" +_CORE_TYPES = {"message", "document", "telemetry", "strings", "event"} +_SIZE_SWEEP_TYPES = { + "size_1": 1, + "size_64": 64, + "size_256": 256, + "size_4096": 4096, + "size_65536": 65536, +} + + def test_catalog_loads_five_types(): cat = load_catalog(_CATALOG) assert cat["data_model_version"] == 2 - assert set(cat["types"]) == {"message", "document", "telemetry", "strings", "event"} + assert _CORE_TYPES <= set(cat["types"]) + + +def test_catalog_size_sweep_types(): + cat = load_catalog(_CATALOG) + assert set(_SIZE_SWEEP_TYPES) <= set(cat["types"]) + for type_id, nbytes in _SIZE_SWEEP_TYPES.items(): + resolved = resolve_type_config(type_id, {}, cat) + assert resolved["payload_bytes"] == nbytes def test_resolve_empty_type_config_fills_defaults(): diff --git a/dashboard/public/data/experiments/13-payload-size-sweep.json.gz b/dashboard/public/data/experiments/13-payload-size-sweep.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..a1c1b96795fe41e9b2501c3863ee8c831ac961b8 GIT binary patch literal 8511 zcmV-FA;8`riwFp4P?u@~|1mQyaAA3DZ((FDb7^{IEpvBeWpFNPb8l_{dXE}VDHZ$Knw>6kYF+3N}L^eDN-gmyPg>P9DX3bSgNVhm(yKEk&=#P zvesE>mR;iQJKa@ZRaaI2_3DS!X0=-$R=4k$hpTU{lu-7a2=9daPo=(5`Wqqs`|A4Y z&!1NN!`*g+fAL=*?`}RW{`en%{C4rM{Jh>SZx{Q!|6T1DHy@XqA6ARQ$JJuD-28aA z`QcyjnMc|C?>`?_`>SvMM_yZVt-xLz5$v@E(Du9QtM8Zl)%tF;N`Dsr;A*$J+1}r; zHn+>iH~#C@?drqw)B5oKetFp4{RLm`uUGizhxhmwOZ;H*o!;Y9@lD4MHhI0DKYqri z&6dU3zn@0UNUetY%ZFW1ET#LwTq z(eYcQciMg0AHG@KY#%<4Z}G6a`4Jzl*UN`JzW?Fwezo}f-@>5G^xUl#Ac|@d01=ez{q^6N3i#TYQzr zKm2gF+aDGW>*dXAakJa*_usFU_wVrLe_Acx{mWv1xP5p3u)kR>@!O0aUwJiXmp>q}Sp4qxcCkgw*2~=wtKD%BAFn?ze*U=HEcV;`DBAq+2?1Mt9~W%Y1LceV z235lC_QQw8@~~L1mN>W6-~aYFd+-e>u;6FdE|&PT17e{Oip6$U>ypR$d)N<)f4{qZ zcYNypXMEz~=extl#d7gsjqhx)VL|TbBSyq2}Sncp_Hish`*W;TUKHlwaGlV#!R>RdV z*H;OgebiqMpAR1&H5tC{;S-KsZGVhwZ~OE9c)Qnk-|v?*3uD`a}GG z{IjzrLmWBacZ!<&aqRl)Zd*M-K?rdcZ1#`;cfY#5TW;Qucj|o{w%Uq8;5%*)%k}&5 z4{E^!h{@yoRr&)X{eU(kUDsEu&7bR6P)~8AcH8u3Nv_{FW157gm5H`NzlOP zl@An*Wqb-F>huu2QO-IQ0D{v~RPp6Mt=_G-H$T2DtX^0}!CjBo!)m#HcZBv$QB?w$Dv4^ABvkW2MpX$Z z5F0302Wvo%LBg5@4Xg-{BWG(Rm;$Q@X`Bn*86~yX7N)>1_n$X6ciZ9ZHL1~7I}+L~ zNzmqj46V`5nL*lg5!w_CC|aE+NsFxuQj*vf!4z9uGFD2fLE)`d;QSQZM@#kg$bt&q zlgMUCLN*U%WI-DbgO~X-grUMI#aOCQ(m<gVxd*3r2X4OQ%t?e_C!n z?cY|v3Xqc`YfJil42^tb$2hbk%KvD|S zlzoC+(FFQ+=#>M8UX6lGug1rPUU{_c9`a>7c(u^$ zP~Z$k!C+**dI}(pLRe=7HYmdYJ4y<$<3I&$2x9Oq zUp;3H^6_T$$c};zS@-B}^vGsGi)_FJgz6*xcPYD?5nTh;(YiECGQUa#gPdighBj7N(!%RU7T3XB1TDXE7J|zE*^BtqjM#$rj#dd-k{MPSC=4qYuLfI~fFVqk z3W~8+qoie6X!1y{PzhRw<&-Kj*PThQ=F|rQCk~?!vZzq3G*VQ86gv1J`0?r|EzWaK ztAs3Ra0L+@$*?LxLjzz4(peS8|MW8$79X*F9gYPY$AX4q!IWbmXB;e)i<-C`$5J%M z5}xK*Y5XM|YgQPe-^awUk|fX7G*G7Mk*+$(S5H@6Bo1U8YZSDED;QF{mhskh86~{a zMmZ5s+qW9vG%c7H+Moq6#9)*ZVlWO=!~j4Js{H6am=zuwd>_mj1syTafr+~4zyt}A zMWdS~&=Cs?Z^1=mc4lw`6Vl3(nsv1yEdgNwldpc>1{LT?VG{Hqtw(A{gtU^NV_n80 z8*obC+(yQ&FJxV_;%n>}fA4u$l4RbM1`6-8-UeKl`J#d^T5!RaM@h%KJkSn95wyGu zeGjyz%KPYN1HeVZYgTxX%?QI#uTfH{*Emq9mp4dsA*8FHz0qLP(>F_6=H&vAHmnk~ z%nQ8r%78Q42W{k;)N5X~fF^*6y%bSa40)s?UrHhMarvkB#}IukzLg{``%>1DQ@0Xy z@huI)L;N&aIxyxL^y}0{_A5Z`6i5>2BuFr)#~EaYlcw-nis5Qy=;@mTEddLGjCq&w zmk_X-ft21!CNh&GWzTCIsP?=Uo0k3{MyZoheg}2_R%aYs$b&X{C}u8igP7 zqRqs);Z2)R6b%E{&@gD?h`~bK)XNtTG>n5cFz{;Q85(9h4X?EUtnzrXQ9CJr5e=Ie zUZtF;9f&N+dy8qH5HYmPIC*rrI(Vf3PkRtq(gKV#kPO;Zf_`^VA<5OKss!GJOXFWN zLu?%9NMuRoVy<;0jPn7liOg3|7CcxwoRB3Q7ju^OB#NNrVxV+T4jnbTZMG!~Pf)R$ z@dfm70z<||Ng-q7Kt;x^bEm@z3LOw8Cnia{IGFUBj)P@E%f^I}An`x^1X{>*cN*tb zzS0ZLIKf#|_*fb#`d3M(<=|w#`Yj#Q(e(7ql9rFb7<23RSP^u540RU@HK2yj$Qz%t z;dnBi^EDWmR}3Q?1(}hJj|(G1lRdbQuAcO2RE{(u8wKr_u2!T9F5@rSb(|YX8Jyra z!zd}7VH~KV3q}mqIb zEXk}P4HSU2Lda1y}LXF@|2&jC;rF*^eV+@+f`bv_5 z@iFN{0ERud&7iUR>uN5P!Xz{HC9YHfzAV1W&CVW5_BUVEEv_D20 z&n~pMzS{0?SG!o^K{2|TlT7UARMWRQX}WwKZ#90nV?6@H9rt7X&ebaPxulU;C^*KBJnZO>F!r;7<9t{{YZgk9rmteX!05I{~tB zYM)&2C#})1A4-Ye6of$YjV^(U>G~Cxjs2;y{O*^>`pdH_! zr`I629E2`c9|hBr$+Q~u3MbPi$f7G1kgQ77#Wq;kRDc||Ki+MRrR;ACDXtxQ=_f&sz>beg z1lHjfm8as|#xrq%Bxu6`LD0oYdAx-Oyd4ZsvFBtZf+J2wikv|7@-Gzr?6wxBB(%6L~|t4#eL5xV*!3m=&tlT)81B|q7?HbcfJUDYg7 zJ2HydEJ%VDSVd=cmGLgNZGw(D=gP|fuFae~gF($&v0xNauwc}*Ucsm)ZO*#ExN;HY z3S2d)rHetmXZC4*cnuCUCyYp^nfyZ`r|E}6HZZDyK7GCj7BxPFfKgB@UyT`fohr@a z9gI@N)F#xWLIn`&OcpgKo}Q`uOoEK3Z)!eGu#-|+qDt8~Cfjfnw0Ih+NIdg+&q@Io zx>IqZQhIIAH%)Uw8U(Y_M?r>kd|W}Q)nIhKhy>Z7n3X;XI-*Z!z)3y>&IO$AN;~BG z=(n0@P}4bUlPp6{lOS)Z*oK^feR8^b&rH`*(B;Mg&7|^pi>)%kDCHEgQy;niCFFF@ zx@2h?#y<)&;~yUv#xH|9&G-!>P1Dm+&`(&!Ojt$-XmAqQhlpkp&^%s9r)Dkr^2}~_ zmJ~weo84?FVh+%$mO2)g48tVo_>?y^pYn$51>-!@I<$U4Bk#DFPR*MuubGVQBq;l< zO*S_e0Z*l7X@&`mg3fZ$RUT#hWrS*8Ah`-~XbQlgt^WohlsOL*0+ zusY3@b0t9z{OP8c3rV7>Gk|(nk?+vqlqBf102BDLT;NaJf~lAKLSi*@K^HPTCVzO8 zl=R_opo&$Y13sM62i6J2q^1apwHim)(UlXb{7N{~0Mcm>M#*3OG*h;T8meq(AX8D#AYQYhJVrwalt)QHc^s%Fut4YbWL>g!Mlch2lyp@E z;Fzic;I>@_SQ}G>&GFw$_}AR%0)8yUZ5SoRZx{#awtL15N~eoZ55{unCP`mL>lIT* z>p6EUieiqUaX6RVrA%z@if# zv5!$9p@TC>2!py{Ct>znY_MrBndo_#Wu@z39x99%k-`a7TJ;g7F-CjG6>bz+UsP)> zS5=!OPjIyJHWg-v*~NCPv?i`(8RjxnRoxpC^9zCycQ=TBJb< zrWmP`^cy=`x)3)YWRPCMrF#(bBW|@cT-T{AD~RWz3UTxTbg2A03UO_O=MYb_7IB=S zn&umoq(dC=b~rCYEN&JTMSSM3uoG5kMw3*s(px3aNiLb1p5t)p(9Nt-0@XkXO-m$#Jl*W|=+~}n-&8aFG z0XI{kTS+>&(R=sa8RVZ@*l>9o)9i>#iJmGQ*{Eb0@iJ8P_>dZ$7`z%ULZ1XHlwfRS zk#&%x;iVhZRFZxd8TETGQaYRn0>TUH#QK{wT_nl)lGLZxUKR74nvts9fq1j3*um8W zPCmw8s~V?Tg1>cDdqrXN%mjnsA^th@#iY@rcnKMLgmjZe- zHwju|t_6KULLTpWcnbySblMfQ)=vNg1moV+rTzDfxa#bc1685q#7M6V@!v%z#{(EV<=TYi31G`&^ynooj+W_nyV?loWT(xJAPs~yDW0>VV3cAhHz;tj7Ome1DK?-Y+Nf*Mw zMI>oXPz`hPVG?9ejcZTdut+@193^7y)-jDSM?v3)MKNty6jPinKo}jjq%ATfd$wJl zv+ymZH#4bMqokx>jRRFDf#as#sUuGvcdTTVbR}BO(Ir}rbdii1>Y3VBzp#dV-rQ`% zB)um=ao3xqcj=U>&*dYg>G%}FTNmc7y!BbpQ`R%qeH3I%G(Ikt2$|hrO3TF_JYedv zlb~JWl1ZbITozRjvG+>(eI{9&8BoSuPl5ty=iX&Rbosy$A&s;-qH@InNpOS2#&OUyBbGO*Yn zB~`UyyVy#}pR5{8&*>-YD0mA?KldRyo{7#ULGe19=)8*jv6__v2u2Ug#>ObinVSLmT4B-SZ7MYF~;#s(|ENX5qo7!P z(}qZ5>!4E+yWnXBI*xaU0)r?ph#C+zq8C~FnPJ77%|uE@LALkf$%xQ0+KG&kR@kT~%PZRe9P&%HzbbnL5>O$!9yTY^GU3v=6GpYf)IZ7k@3_y=7^0o5$yNKIUU;Vsv{?iLILGirV6udPc z1t=?3JTR`BOukD6KfONBDkDL>;>mkKpgSYIl%h&HKDshbF23`U>GPK*v3l7ObW>cW zsM%+%x$Cn4)f}KYb}`nVkWxKH@H3#Tsi?t?N!&O4kIUV|Sqa?VZZ|idcDvQ)@P{|g zrPEv^1Ko5n&}|C?9Z#FkRdZw_;K@adEg3ORf#jZLit~KSBYgkF9hN#9hPdRo9$lho z(bZsRV^(l(PC&IM(2~J03A!H0G=^oo+tIYspDCojk7(X)e)x8~UaxL&b!^`DTnTPR zBQ!f2q2194!Qc`t$I4KdvkbIJ(B^^wbFKu?&?1?g0PDVvZ24d~NKFH&X(2^UGjnwNXvK&scdN26w`0N#3>z$-*xM@-THmEc$C!1st)71Y3fN#ZJ;qN z<81|kIHds2Fivx3*h$Vj$;Ld%);vjYb=O`;ML{_GAwKActm5HUv z)rrS4yx2s6q`@uYor$WDMWDZy^zXn?s?boX&{C@49h|P10gh4uO{tQe?W;RjBbDHM zME7hPHD`H;0@g}FYo(yIQpzefD3>py`7vkt4Q=^T;aCf58Sku=Rtmg`K6P}cFSb%M zXWt1f`%X03ccLu;v2w5{&*}Qg{HS^Ro^xc%HeAZKRLaJNr>AlnG;ppIyoxJz41@+G zBH9?Q9C-M8vO_&LKYcSleLFvWnDVHXFa1l;=Zk)n4;DZ=Wg^7pISgP{cmqdMLqk)8 z?0qUzwQwVvE*UQG&ZyTiS0|_Kw_mEG{EPf5rM*0Tx|HGAzoFT`V~DHMoW)X;dFwB> zSaau(al}b|-GaRon_O+r_Q(&KE zxaJ1<1G#=&>kabo`9%CK6TdZG($ozKjC}FLz1(!2 z)ClK<1m{oVP6EO9O-R8n5~Db~qhi8XaI-9RTrE6YcWli9+E%;{zTW8OO z7ToI3lIk2!(H)HbWZ3mW*8rF;7YH26O#;aI5yCfUy3axD+Bl)>;)Kpm_p^IWV7cI{ zm5gfDoNi@|mmSng^Y(fJH&M{!Dwt}WZ~JbZ{fkbsg(g3Knl3cyF+1sNNPL!alZ9kV zX-U6jm1Wj$2$s|qcwW-pKL(!DAeEW`I*naF1?U-Rdrv?*MUMpdVn_oI=?jzlx=_he z0G*ZG_x~Lt5tBWoR2l++04sfsSi{htT%+gZ_WcSla}JPN`hdjV9@EGZX3;RzFdeh> z&PveRKkRSb?eLqvaiWf4@^s8JO=nu75Ud-ZF83nn4RZp#qmR<0yDvI*mTPnW>9G3C z7ibcQYL;nwqoxh7(&H*8$C<%ZyPds*=qz2vIgYpVP?1eW@^E+bffLRuC#AQ>pkn+w z^2S~QD8O*)Uop_yTiN#{fFrY;ly7Zj0kUg{JkguID5&9CXmksjh)4 z=k&^vHArQ=!PE@K87Qc>eQ-|c%UM%#Jd=szr-?Ye(U^Wvb-^5wg9l6s9*{e5hTecP zuc0w#?E$JRGcA>!&Prw5NvYzT$X7op9n(_4ku3#)K5`tm6UVg;UK=NcGun&x_~tK{ z$b?7*4${y-8hSHSbq^yd;vCcZ*O8rnnPNDm7B1>d6}0x=sNmw+UT5pgIpH)yNv@Zj zl1(!^C7VXI0=d!2R2u;9{AM7JZ}!HM#;A<*O%3uUoyu=vPUSk=O^l}LxXdt3DV399ngk{fFO%FGcPhnb3@AUB;C*? z-Lj;Z|54@DP@poblPrM;`k-sz&bijk+F15#!5g$n`fTkvcPmh)S9O-u`ct&}GqxHi zjRNHt(Vy1GBg8>^0SNB}`g7)8-{<=4@$t!R^b6f}NxSRvH5BOV8|Q)BHxJFWd1wo1 z;?#t45l$vBP9~5}CcWGhx7@8o<7X6-Chw6AU!+6lM)d`>9;c128UPcpGUnZp=KWIB zgc`?MiF`hoAffGbaYBpE4rvG+rlX{QIu2B*h5*A!hZEJM=JY7(!5jKik22orQLn0? zi1U|t@N;iMK3kLO!K&)|va0kcKYsp>Va$QBNl+X8DxFae=fzf(0bo&M>j)u&HZPn~SD8E?Ig&A*Wx9k*EN zZMJqpyng#LPqU4OcM5b5td21`Umx(<1&+&xoOxbu!3pT$e~)WUI?!M zg4SV*+%$0X6mn-I5ljG>pfyGEl4&+ul0fhJJ%zwoSpr`>2Jz+MNq6` + Same SPSC handoff, five payload sizes (1 B, 64 B, 256 B, 4 KiB, 64 KiB). + Which sizes produce a different ranking, and which are just more of the + same? +story: + why: > + The default suite names five data types, but every runner builds an + opaque byte string of a chosen length. If ranking only moves at a + couple of lengths, the published matrix should keep those lengths and + drop the rest. + example: > + A ticket is a few hundred bytes. An HTTP body is a few kilobytes. A + file chunk can be tens of kilobytes. We need to know which of those + worlds actually changes which queue wins. + tradeoff: > + Extra sizes cost machine time and make the dashboard harder to read. + One size is enough if copy cost never changes the order. Two sizes + are enough if a small payload and a large payload tell different + stories. + +sample: + kind: size_256 + records_per_write: 100 + seed: 42 + settings: + sweep_bytes: [1, 64, 256, 4096, 65536] + saved_as: sample.json + +run: + mode: full + io_modes: [bytes] + compression: none + soft_seconds_per_10_serializers: 60 + hard_cap_seconds: 600 + reps_fallback: 100 + +analysis: + drop_first_trial: true + filter_id: iqr_1.5 + main_io: bytes + baseline_bytes: 256 + top_group: + method: cliffs_delta_vs_fastest + similar_max: 0.147 + close_max: 0.33 + +paths: + results: results.json + summary: results.md + +languages: + - id: python + enabled: true + libraries: + - {name: deque-lock, role: locked baseline} + - {name: queue.Queue, role: threading MPMC used as SPSC} + - {name: queue.SimpleQueue, role: unbounded threading MPMC used as SPSC} + - {name: asyncio.Queue, role: event-loop queue} + - {name: janus, role: third-party async queue} + - id: rust + enabled: true + libraries: + - {name: std-mpsc, role: standard MPSC} + - {name: crossbeam-channel, role: MPMC channel} + - {name: flume, role: third-party MPMC} + - {name: crossbeam-queue, role: lock-free MPMC} + - {name: tokio-mpsc, role: async MPSC} + - {name: async-channel, role: async MPMC} + - id: javascript + enabled: true + libraries: + - {name: Array, role: push/shift baseline} + - {name: denque, role: O(1) circular FIFO} + - {name: yocto-queue, role: O(1) linked-list FIFO} + - {name: fastq, role: job queue} + - {name: p-queue, role: scheduler (not ranked as a queue)} + - id: csharp + enabled: true + libraries: + - {name: Queue+lock, role: locked baseline} + - {name: ConcurrentQueue, role: concurrent MPMC} + - {name: BlockingCollection, role: blocking MPMC} + - {name: Channel, role: async channel} + - id: c + enabled: true + libraries: + - {name: mutex-queue, role: locked ring} + - {name: lfqueue, role: lock-free MPMC} + - {name: spsc-ring, role: SPSC ring} diff --git a/experiments/13-payload-size-sweep/javascript/results.json b/experiments/13-payload-size-sweep/javascript/results.json new file mode 100644 index 0000000..c01ac5c --- /dev/null +++ b/experiments/13-payload-size-sweep/javascript/results.json @@ -0,0 +1,659 @@ +{ + "status": "ok", + "rows": [ + { + "library": "fastq", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1473.0, + "total_median_ns": 1473.0, + "p50_ns": 1473.0, + "mean_ns": 2441.2323232323233, + "enq_median_ns": 1473.0, + "write_median_ns": 1473.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3539.0, + "total_median_ns": 3539.0, + "p50_ns": 3539.0, + "mean_ns": 7782.585858585859, + "enq_median_ns": 2259.0, + "write_median_ns": 2259.0, + "deq_median_ns": 1307.0, + "read_median_ns": 1307.0, + "rel_to_fastest": 2.4025797691785473 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6797.0, + "total_median_ns": 6797.0, + "p50_ns": 6797.0, + "mean_ns": 5479.606060606061, + "enq_median_ns": 3056.0, + "write_median_ns": 3056.0, + "deq_median_ns": 3696.0, + "read_median_ns": 3696.0, + "rel_to_fastest": 4.61439239646979 + }, + { + "library": "yocto-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7600.0, + "total_median_ns": 7600.0, + "p50_ns": 7600.0, + "mean_ns": 10208.030303030304, + "enq_median_ns": 3549.0, + "write_median_ns": 3549.0, + "deq_median_ns": 4002.0, + "read_median_ns": 4002.0, + "rel_to_fastest": 5.159538357094365 + }, + { + "library": "Array", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8629.0, + "total_median_ns": 8629.0, + "p50_ns": 8629.0, + "mean_ns": 16840.757575757576, + "enq_median_ns": 4489.0, + "write_median_ns": 4489.0, + "deq_median_ns": 3862.0, + "read_median_ns": 3862.0, + "rel_to_fastest": 5.858112695179905 + }, + { + "library": "p-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 60642.0, + "total_median_ns": 60642.0, + "p50_ns": 60642.0, + "mean_ns": 84921.41414141415, + "enq_median_ns": 55802.0, + "write_median_ns": 55802.0, + "deq_median_ns": 4863.0, + "read_median_ns": 4863.0, + "rel_to_fastest": 41.169042769857434 + }, + { + "library": "fastq", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1388.0, + "total_median_ns": 1388.0, + "p50_ns": 1388.0, + "mean_ns": 1489.030303030303, + "enq_median_ns": 1388.0, + "write_median_ns": 1388.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Array", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2520.0, + "total_median_ns": 2520.0, + "p50_ns": 2520.0, + "mean_ns": 2825.131313131313, + "enq_median_ns": 806.0, + "write_median_ns": 806.0, + "deq_median_ns": 1715.0, + "read_median_ns": 1715.0, + "rel_to_fastest": 1.8155619596541788 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2811.0, + "total_median_ns": 2811.0, + "p50_ns": 2811.0, + "mean_ns": 2928.3636363636365, + "enq_median_ns": 974.0, + "write_median_ns": 974.0, + "deq_median_ns": 1829.0, + "read_median_ns": 1829.0, + "rel_to_fastest": 2.0252161383285303 + }, + { + "library": "denque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3094.0, + "total_median_ns": 3094.0, + "p50_ns": 3094.0, + "mean_ns": 6515.131313131313, + "enq_median_ns": 1768.0, + "write_median_ns": 1768.0, + "deq_median_ns": 1296.0, + "read_median_ns": 1296.0, + "rel_to_fastest": 2.229106628242075 + }, + { + "library": "yocto-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3477.0, + "total_median_ns": 3477.0, + "p50_ns": 3477.0, + "mean_ns": 4669.636363636364, + "enq_median_ns": 1677.0, + "write_median_ns": 1677.0, + "deq_median_ns": 1792.0, + "read_median_ns": 1792.0, + "rel_to_fastest": 2.505043227665706 + }, + { + "library": "p-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62336.0, + "total_median_ns": 62336.0, + "p50_ns": 62336.0, + "mean_ns": 89398.06060606061, + "enq_median_ns": 57891.0, + "write_median_ns": 57891.0, + "deq_median_ns": 4277.0, + "read_median_ns": 4277.0, + "rel_to_fastest": 44.91066282420749 + }, + { + "library": "fastq", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1404.0, + "total_median_ns": 1404.0, + "p50_ns": 1404.0, + "mean_ns": 1722.939393939394, + "enq_median_ns": 1404.0, + "write_median_ns": 1404.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2680.0, + "total_median_ns": 2680.0, + "p50_ns": 2680.0, + "mean_ns": 2743.40404040404, + "enq_median_ns": 1578.0, + "write_median_ns": 1578.0, + "deq_median_ns": 1108.0, + "read_median_ns": 1108.0, + "rel_to_fastest": 1.9088319088319088 + }, + { + "library": "Array", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2697.0, + "total_median_ns": 2697.0, + "p50_ns": 2697.0, + "mean_ns": 2718.5858585858587, + "enq_median_ns": 897.0, + "write_median_ns": 897.0, + "deq_median_ns": 1793.0, + "read_median_ns": 1793.0, + "rel_to_fastest": 1.920940170940171 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2980.0, + "total_median_ns": 2980.0, + "p50_ns": 2980.0, + "mean_ns": 3878.2020202020203, + "enq_median_ns": 1009.0, + "write_median_ns": 1009.0, + "deq_median_ns": 1976.0, + "read_median_ns": 1976.0, + "rel_to_fastest": 2.1225071225071224 + }, + { + "library": "yocto-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3556.0, + "total_median_ns": 3556.0, + "p50_ns": 3556.0, + "mean_ns": 4644.89898989899, + "enq_median_ns": 1736.0, + "write_median_ns": 1736.0, + "deq_median_ns": 1837.0, + "read_median_ns": 1837.0, + "rel_to_fastest": 2.532763532763533 + }, + { + "library": "p-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 45134.0, + "total_median_ns": 45134.0, + "p50_ns": 45134.0, + "mean_ns": 60979.606060606064, + "enq_median_ns": 41557.0, + "write_median_ns": 41557.0, + "deq_median_ns": 3615.0, + "read_median_ns": 3615.0, + "rel_to_fastest": 32.14672364672364 + }, + { + "library": "fastq", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1200.0, + "total_median_ns": 1200.0, + "p50_ns": 1200.0, + "mean_ns": 1311.8181818181818, + "enq_median_ns": 1200.0, + "write_median_ns": 1200.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2839.0, + "total_median_ns": 2839.0, + "p50_ns": 2839.0, + "mean_ns": 2891.6060606060605, + "enq_median_ns": 1653.0, + "write_median_ns": 1653.0, + "deq_median_ns": 1182.0, + "read_median_ns": 1182.0, + "rel_to_fastest": 2.3658333333333332 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2839.0, + "total_median_ns": 2839.0, + "p50_ns": 2839.0, + "mean_ns": 2913.070707070707, + "enq_median_ns": 939.0, + "write_median_ns": 939.0, + "deq_median_ns": 1902.0, + "read_median_ns": 1902.0, + "rel_to_fastest": 2.3658333333333332 + }, + { + "library": "Array", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2941.0, + "total_median_ns": 2941.0, + "p50_ns": 2941.0, + "mean_ns": 2987.030303030303, + "enq_median_ns": 987.0, + "write_median_ns": 987.0, + "deq_median_ns": 1952.0, + "read_median_ns": 1952.0, + "rel_to_fastest": 2.450833333333333 + }, + { + "library": "yocto-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3654.0, + "total_median_ns": 3654.0, + "p50_ns": 3654.0, + "mean_ns": 6775.888888888889, + "enq_median_ns": 1779.0, + "write_median_ns": 1779.0, + "deq_median_ns": 1861.0, + "read_median_ns": 1861.0, + "rel_to_fastest": 3.045 + }, + { + "library": "p-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43584.0, + "total_median_ns": 43584.0, + "p50_ns": 43584.0, + "mean_ns": 53845.15151515151, + "enq_median_ns": 40070.0, + "write_median_ns": 40070.0, + "deq_median_ns": 3551.0, + "read_median_ns": 3551.0, + "rel_to_fastest": 36.32 + }, + { + "library": "fastq", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1233.0, + "total_median_ns": 1233.0, + "p50_ns": 1233.0, + "mean_ns": 1354.1515151515152, + "enq_median_ns": 1233.0, + "write_median_ns": 1233.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2825.0, + "total_median_ns": 2825.0, + "p50_ns": 2825.0, + "mean_ns": 2846.3333333333335, + "enq_median_ns": 880.0, + "write_median_ns": 880.0, + "deq_median_ns": 1926.0, + "read_median_ns": 1926.0, + "rel_to_fastest": 2.291159772911598 + }, + { + "library": "Array", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2985.0, + "total_median_ns": 2985.0, + "p50_ns": 2985.0, + "mean_ns": 3039.959595959596, + "enq_median_ns": 982.0, + "write_median_ns": 982.0, + "deq_median_ns": 1987.0, + "read_median_ns": 1987.0, + "rel_to_fastest": 2.420924574209246 + }, + { + "library": "denque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3043.0, + "total_median_ns": 3043.0, + "p50_ns": 3043.0, + "mean_ns": 3080.4242424242425, + "enq_median_ns": 1788.0, + "write_median_ns": 1788.0, + "deq_median_ns": 1239.0, + "read_median_ns": 1239.0, + "rel_to_fastest": 2.467964314679643 + }, + { + "library": "yocto-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3674.0, + "total_median_ns": 3674.0, + "p50_ns": 3674.0, + "mean_ns": 6320.363636363636, + "enq_median_ns": 1776.0, + "write_median_ns": 1776.0, + "deq_median_ns": 1888.0, + "read_median_ns": 1888.0, + "rel_to_fastest": 2.9797242497972425 + }, + { + "library": "p-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43742.0, + "total_median_ns": 43742.0, + "p50_ns": 43742.0, + "mean_ns": 51323.0404040404, + "enq_median_ns": 40151.0, + "write_median_ns": 40151.0, + "deq_median_ns": 3537.0, + "read_median_ns": 3537.0, + "rel_to_fastest": 35.47607461476075 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "fastq", + "denque", + "steal-deque", + "yocto-queue", + "Array", + "p-queue" + ], + "first": "fastq", + "spearman": 0.8285714285714286, + "kendall": 0.7333333333333333, + "flips": [ + "Array vs steal-deque", + "Array vs yocto-queue" + ], + "flip_count": 2, + "time_ratio_median": 2.137232845894263, + "spread": 41.169042769857434, + "n_libs": 6 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "fastq", + "Array", + "steal-deque", + "denque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.8285714285714286, + "kendall": 0.7333333333333333, + "flips": [ + "denque vs Array", + "denque vs steal-deque" + ], + "flip_count": 2, + "time_ratio_median": 0.9886039886039886, + "spread": 44.91066282420749, + "n_libs": 6 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "fastq", + "denque", + "Array", + "steal-deque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 1.0, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 32.14672364672364, + "n_libs": 6 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "fastq", + "denque", + "steal-deque", + "Array", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.898645105261295, + "kendall": 0.8571428571428571, + "flips": [ + "Array vs steal-deque" + ], + "flip_count": 1, + "time_ratio_median": 1.0275590551181102, + "spread": 36.32, + "n_libs": 6 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "fastq", + "steal-deque", + "Array", + "denque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.7714285714285715, + "kendall": 0.6, + "flips": [ + "denque vs Array", + "denque vs steal-deque", + "Array vs steal-deque" + ], + "flip_count": 3, + "time_ratio_median": 1.0331833520809899, + "spread": 35.47607461476075, + "n_libs": 6 + } + ] +} \ No newline at end of file diff --git a/experiments/13-payload-size-sweep/javascript/results.md b/experiments/13-payload-size-sweep/javascript/results.md new file mode 100644 index 0000000..b6c949b --- /dev/null +++ b/experiments/13-payload-size-sweep/javascript/results.md @@ -0,0 +1,72 @@ +# javascript + +Times are not comparable across languages. + +## size_1 (1 B) + +vs 256 B: Spearman 0.829, Kendall 0.733, 2 pairwise flip(s), time × 2.14. +Flips: Array vs steal-deque; Array vs yocto-queue. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| fastq | 1473 | 1.00× | 99 | +| denque | 3539 | 2.40× | 99 | +| steal-deque | 6797 | 4.61× | 99 | +| yocto-queue | 7600 | 5.16× | 99 | +| Array | 8629 | 5.86× | 99 | +| p-queue | 60642 | 41.17× | 99 | + +## size_64 (64 B) + +vs 256 B: Spearman 0.829, Kendall 0.733, 2 pairwise flip(s), time × 0.99. +Flips: denque vs Array; denque vs steal-deque. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| fastq | 1388 | 1.00× | 99 | +| Array | 2520 | 1.82× | 99 | +| steal-deque | 2811 | 2.03× | 99 | +| denque | 3094 | 2.23× | 99 | +| yocto-queue | 3477 | 2.51× | 99 | +| p-queue | 62336 | 44.91× | 99 | + +## size_256 (256 B) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 1.00. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| fastq | 1404 | 1.00× | 99 | +| denque | 2680 | 1.91× | 99 | +| Array | 2697 | 1.92× | 99 | +| steal-deque | 2980 | 2.12× | 99 | +| yocto-queue | 3556 | 2.53× | 99 | +| p-queue | 45134 | 32.15× | 99 | + +## size_4096 (4 KiB) + +vs 256 B: Spearman 0.899, Kendall 0.857, 1 pairwise flip(s), time × 1.03. +Flips: Array vs steal-deque. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| fastq | 1200 | 1.00× | 99 | +| denque | 2839 | 2.37× | 99 | +| steal-deque | 2839 | 2.37× | 99 | +| Array | 2941 | 2.45× | 99 | +| yocto-queue | 3654 | 3.04× | 99 | +| p-queue | 43584 | 36.32× | 99 | + +## size_65536 (64 KiB) + +vs 256 B: Spearman 0.771, Kendall 0.600, 3 pairwise flip(s), time × 1.03. +Flips: denque vs Array; denque vs steal-deque; Array vs steal-deque. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| fastq | 1233 | 1.00× | 99 | +| steal-deque | 2825 | 2.29× | 99 | +| Array | 2985 | 2.42× | 99 | +| denque | 3043 | 2.47× | 99 | +| yocto-queue | 3674 | 2.98× | 99 | +| p-queue | 43742 | 35.48× | 99 | diff --git a/experiments/13-payload-size-sweep/python/results.json b/experiments/13-payload-size-sweep/python/results.json new file mode 100644 index 0000000..7cdc98d --- /dev/null +++ b/experiments/13-payload-size-sweep/python/results.json @@ -0,0 +1,744 @@ +{ + "status": "ok", + "rows": [ + { + "library": "queue.SimpleQueue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6360.0, + "total_median_ns": 6360.0, + "p50_ns": 6360.0, + "mean_ns": 6418.20202020202, + "enq_median_ns": 2735.0, + "write_median_ns": 2735.0, + "deq_median_ns": 3617.0, + "read_median_ns": 3617.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 15263.0, + "total_median_ns": 15263.0, + "p50_ns": 15263.0, + "mean_ns": 15604.868686868687, + "enq_median_ns": 7007.0, + "write_median_ns": 7007.0, + "deq_median_ns": 8289.0, + "read_median_ns": 8289.0, + "rel_to_fastest": 2.3998427672955973 + }, + { + "library": "deque-lock", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 18062.0, + "total_median_ns": 18062.0, + "p50_ns": 18062.0, + "mean_ns": 18166.80808080808, + "enq_median_ns": 8358.0, + "write_median_ns": 8358.0, + "deq_median_ns": 9706.0, + "read_median_ns": 9706.0, + "rel_to_fastest": 2.839937106918239 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 20020.0, + "total_median_ns": 20020.0, + "p50_ns": 20020.0, + "mean_ns": 20108.050505050505, + "enq_median_ns": 9357.0, + "write_median_ns": 9357.0, + "deq_median_ns": 10679.0, + "read_median_ns": 10679.0, + "rel_to_fastest": 3.147798742138365 + }, + { + "library": "asyncio.Queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43637.0, + "total_median_ns": 43637.0, + "p50_ns": 43637.0, + "mean_ns": 43774.16161616162, + "enq_median_ns": 25452.0, + "write_median_ns": 25452.0, + "deq_median_ns": 17911.0, + "read_median_ns": 17911.0, + "rel_to_fastest": 6.861163522012578 + }, + { + "library": "queue.Queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 52988.0, + "total_median_ns": 52988.0, + "p50_ns": 52988.0, + "mean_ns": 53485.818181818184, + "enq_median_ns": 27147.0, + "write_median_ns": 27147.0, + "deq_median_ns": 25599.0, + "read_median_ns": 25599.0, + "rel_to_fastest": 8.331446540880503 + }, + { + "library": "janus", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 105187.0, + "total_median_ns": 105187.0, + "p50_ns": 105187.0, + "mean_ns": 108440.06060606061, + "enq_median_ns": 55364.0, + "write_median_ns": 55364.0, + "deq_median_ns": 49556.0, + "read_median_ns": 49556.0, + "rel_to_fastest": 16.53883647798742 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6750.0, + "total_median_ns": 6750.0, + "p50_ns": 6750.0, + "mean_ns": 6807.858585858586, + "enq_median_ns": 3037.0, + "write_median_ns": 3037.0, + "deq_median_ns": 3719.0, + "read_median_ns": 3719.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 15177.0, + "total_median_ns": 15177.0, + "p50_ns": 15177.0, + "mean_ns": 15857.0, + "enq_median_ns": 6891.0, + "write_median_ns": 6891.0, + "deq_median_ns": 8335.0, + "read_median_ns": 8335.0, + "rel_to_fastest": 2.2484444444444445 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19446.0, + "total_median_ns": 19446.0, + "p50_ns": 19446.0, + "mean_ns": 19425.41414141414, + "enq_median_ns": 9013.0, + "write_median_ns": 9013.0, + "deq_median_ns": 10400.0, + "read_median_ns": 10400.0, + "rel_to_fastest": 2.880888888888889 + }, + { + "library": "deque-lock", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19924.0, + "total_median_ns": 19924.0, + "p50_ns": 19924.0, + "mean_ns": 19990.878787878788, + "enq_median_ns": 9146.0, + "write_median_ns": 9146.0, + "deq_median_ns": 10763.0, + "read_median_ns": 10763.0, + "rel_to_fastest": 2.9517037037037035 + }, + { + "library": "asyncio.Queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 45670.0, + "total_median_ns": 45670.0, + "p50_ns": 45670.0, + "mean_ns": 47104.93939393939, + "enq_median_ns": 26744.0, + "write_median_ns": 26744.0, + "deq_median_ns": 18637.0, + "read_median_ns": 18637.0, + "rel_to_fastest": 6.765925925925926 + }, + { + "library": "queue.Queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58876.0, + "total_median_ns": 58876.0, + "p50_ns": 58876.0, + "mean_ns": 59482.606060606064, + "enq_median_ns": 30292.0, + "write_median_ns": 30292.0, + "deq_median_ns": 28580.0, + "read_median_ns": 28580.0, + "rel_to_fastest": 8.72237037037037 + }, + { + "library": "janus", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 107444.0, + "total_median_ns": 107444.0, + "p50_ns": 107444.0, + "mean_ns": 110398.9898989899, + "enq_median_ns": 56786.0, + "write_median_ns": 56786.0, + "deq_median_ns": 50976.0, + "read_median_ns": 50976.0, + "rel_to_fastest": 15.91762962962963 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6755.0, + "total_median_ns": 6755.0, + "p50_ns": 6755.0, + "mean_ns": 6779.656565656565, + "enq_median_ns": 3027.0, + "write_median_ns": 3027.0, + "deq_median_ns": 3708.0, + "read_median_ns": 3708.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 16353.0, + "total_median_ns": 16353.0, + "p50_ns": 16353.0, + "mean_ns": 16807.757575757576, + "enq_median_ns": 7425.0, + "write_median_ns": 7425.0, + "deq_median_ns": 8947.0, + "read_median_ns": 8947.0, + "rel_to_fastest": 2.4208734270910437 + }, + { + "library": "deque-lock", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19305.0, + "total_median_ns": 19305.0, + "p50_ns": 19305.0, + "mean_ns": 19551.222222222223, + "enq_median_ns": 8919.0, + "write_median_ns": 8919.0, + "deq_median_ns": 10399.0, + "read_median_ns": 10399.0, + "rel_to_fastest": 2.857883049592894 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19920.0, + "total_median_ns": 19920.0, + "p50_ns": 19920.0, + "mean_ns": 20059.545454545456, + "enq_median_ns": 9298.0, + "write_median_ns": 9298.0, + "deq_median_ns": 10624.0, + "read_median_ns": 10624.0, + "rel_to_fastest": 2.9489267209474463 + }, + { + "library": "asyncio.Queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 46617.0, + "total_median_ns": 46617.0, + "p50_ns": 46617.0, + "mean_ns": 46869.42424242424, + "enq_median_ns": 27130.0, + "write_median_ns": 27130.0, + "deq_median_ns": 18850.0, + "read_median_ns": 18850.0, + "rel_to_fastest": 6.9011102886750555 + }, + { + "library": "queue.Queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58004.0, + "total_median_ns": 58004.0, + "p50_ns": 58004.0, + "mean_ns": 58470.59595959596, + "enq_median_ns": 29638.0, + "write_median_ns": 29638.0, + "deq_median_ns": 27958.0, + "read_median_ns": 27958.0, + "rel_to_fastest": 8.586824574389341 + }, + { + "library": "janus", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 110450.0, + "total_median_ns": 110450.0, + "p50_ns": 110450.0, + "mean_ns": 112215.77777777778, + "enq_median_ns": 58464.0, + "write_median_ns": 58464.0, + "deq_median_ns": 52660.0, + "read_median_ns": 52660.0, + "rel_to_fastest": 16.350851221317544 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7251.0, + "total_median_ns": 7251.0, + "p50_ns": 7251.0, + "mean_ns": 7245.989898989899, + "enq_median_ns": 3248.0, + "write_median_ns": 3248.0, + "deq_median_ns": 3991.0, + "read_median_ns": 3991.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 18716.0, + "total_median_ns": 18716.0, + "p50_ns": 18716.0, + "mean_ns": 18997.363636363636, + "enq_median_ns": 8489.0, + "write_median_ns": 8489.0, + "deq_median_ns": 10273.0, + "read_median_ns": 10273.0, + "rel_to_fastest": 2.5811612191421873 + }, + { + "library": "deque-lock", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19357.0, + "total_median_ns": 19357.0, + "p50_ns": 19357.0, + "mean_ns": 19652.838383838385, + "enq_median_ns": 8989.0, + "write_median_ns": 8989.0, + "deq_median_ns": 10348.0, + "read_median_ns": 10348.0, + "rel_to_fastest": 2.669562818921528 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 22783.0, + "total_median_ns": 22783.0, + "p50_ns": 22783.0, + "mean_ns": 22882.535353535353, + "enq_median_ns": 10585.0, + "write_median_ns": 10585.0, + "deq_median_ns": 12185.0, + "read_median_ns": 12185.0, + "rel_to_fastest": 3.142049372500345 + }, + { + "library": "asyncio.Queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 47305.0, + "total_median_ns": 47305.0, + "p50_ns": 47305.0, + "mean_ns": 47896.31313131313, + "enq_median_ns": 28566.0, + "write_median_ns": 28566.0, + "deq_median_ns": 18769.0, + "read_median_ns": 18769.0, + "rel_to_fastest": 6.523927734105641 + }, + { + "library": "queue.Queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58309.0, + "total_median_ns": 58309.0, + "p50_ns": 58309.0, + "mean_ns": 58677.656565656565, + "enq_median_ns": 29925.0, + "write_median_ns": 29925.0, + "deq_median_ns": 28183.0, + "read_median_ns": 28183.0, + "rel_to_fastest": 8.041511515653013 + }, + { + "library": "janus", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 118035.0, + "total_median_ns": 118035.0, + "p50_ns": 118035.0, + "mean_ns": 121731.71717171717, + "enq_median_ns": 61966.0, + "write_median_ns": 61966.0, + "deq_median_ns": 55444.0, + "read_median_ns": 55444.0, + "rel_to_fastest": 16.278444352503104 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7821.0, + "total_median_ns": 7821.0, + "p50_ns": 7821.0, + "mean_ns": 7873.79797979798, + "enq_median_ns": 3493.0, + "write_median_ns": 3493.0, + "deq_median_ns": 4325.0, + "read_median_ns": 4325.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19707.0, + "total_median_ns": 19707.0, + "p50_ns": 19707.0, + "mean_ns": 20040.646464646463, + "enq_median_ns": 8954.0, + "write_median_ns": 8954.0, + "deq_median_ns": 10751.0, + "read_median_ns": 10751.0, + "rel_to_fastest": 2.5197545070962795 + }, + { + "library": "deque-lock", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 23091.0, + "total_median_ns": 23091.0, + "p50_ns": 23091.0, + "mean_ns": 23207.121212121212, + "enq_median_ns": 10747.0, + "write_median_ns": 10747.0, + "deq_median_ns": 12346.0, + "read_median_ns": 12346.0, + "rel_to_fastest": 2.9524357499041045 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 23530.0, + "total_median_ns": 23530.0, + "p50_ns": 23530.0, + "mean_ns": 23596.151515151516, + "enq_median_ns": 11054.0, + "write_median_ns": 11054.0, + "deq_median_ns": 12519.0, + "read_median_ns": 12519.0, + "rel_to_fastest": 3.0085666794527555 + }, + { + "library": "asyncio.Queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 53915.0, + "total_median_ns": 53915.0, + "p50_ns": 53915.0, + "mean_ns": 54091.979797979795, + "enq_median_ns": 31335.0, + "write_median_ns": 31335.0, + "deq_median_ns": 21617.0, + "read_median_ns": 21617.0, + "rel_to_fastest": 6.893619741721007 + }, + { + "library": "queue.Queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 66819.0, + "total_median_ns": 66819.0, + "p50_ns": 66819.0, + "mean_ns": 67272.19191919192, + "enq_median_ns": 34449.0, + "write_median_ns": 34449.0, + "deq_median_ns": 32220.0, + "read_median_ns": 32220.0, + "rel_to_fastest": 8.543536632144226 + }, + { + "library": "janus", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 128735.0, + "total_median_ns": 128735.0, + "p50_ns": 128735.0, + "mean_ns": 128821.04040404041, + "enq_median_ns": 67347.0, + "write_median_ns": 67347.0, + "deq_median_ns": 60493.0, + "read_median_ns": 60493.0, + "rel_to_fastest": 16.460171333589056 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 0.9360748224896497, + "spread": 16.53883647798742, + "n_libs": 7 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "steal-deque", + "deque-lock", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9642857142857142, + "kendall": 0.9047619047619048, + "flips": [ + "deque-lock vs steal-deque" + ], + "flip_count": 1, + "time_ratio_median": 0.9796855224488921, + "spread": 15.91762962962963, + "n_libs": 7 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 16.350851221317544, + "n_libs": 7 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.068673607967406, + "spread": 16.278444352503104, + "n_libs": 7 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.1655500226346762, + "spread": 16.460171333589056, + "n_libs": 7 + } + ] +} \ No newline at end of file diff --git a/experiments/13-payload-size-sweep/python/results.md b/experiments/13-payload-size-sweep/python/results.md new file mode 100644 index 0000000..71b0ffb --- /dev/null +++ b/experiments/13-payload-size-sweep/python/results.md @@ -0,0 +1,74 @@ +# python + +Times are not comparable across languages. + +## size_1 (1 B) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 0.94. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| queue.SimpleQueue | 6360 | 1.00× | 99 | +| spsc-ring | 15263 | 2.40× | 99 | +| deque-lock | 18062 | 2.84× | 99 | +| steal-deque | 20020 | 3.15× | 99 | +| asyncio.Queue | 43637 | 6.86× | 99 | +| queue.Queue | 52988 | 8.33× | 99 | +| janus | 105187 | 16.54× | 99 | + +## size_64 (64 B) + +vs 256 B: Spearman 0.964, Kendall 0.905, 1 pairwise flip(s), time × 0.98. +Flips: deque-lock vs steal-deque. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| queue.SimpleQueue | 6750 | 1.00× | 99 | +| spsc-ring | 15177 | 2.25× | 99 | +| steal-deque | 19446 | 2.88× | 99 | +| deque-lock | 19924 | 2.95× | 99 | +| asyncio.Queue | 45670 | 6.77× | 99 | +| queue.Queue | 58876 | 8.72× | 99 | +| janus | 107444 | 15.92× | 99 | + +## size_256 (256 B) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 1.00. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| queue.SimpleQueue | 6755 | 1.00× | 99 | +| spsc-ring | 16353 | 2.42× | 99 | +| deque-lock | 19305 | 2.86× | 99 | +| steal-deque | 19920 | 2.95× | 99 | +| asyncio.Queue | 46617 | 6.90× | 99 | +| queue.Queue | 58004 | 8.59× | 99 | +| janus | 110450 | 16.35× | 99 | + +## size_4096 (4 KiB) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 1.07. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| queue.SimpleQueue | 7251 | 1.00× | 99 | +| spsc-ring | 18716 | 2.58× | 99 | +| deque-lock | 19357 | 2.67× | 99 | +| steal-deque | 22783 | 3.14× | 99 | +| asyncio.Queue | 47305 | 6.52× | 99 | +| queue.Queue | 58309 | 8.04× | 99 | +| janus | 118035 | 16.28× | 99 | + +## size_65536 (64 KiB) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 1.17. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| queue.SimpleQueue | 7821 | 1.00× | 99 | +| spsc-ring | 19707 | 2.52× | 99 | +| deque-lock | 23091 | 2.95× | 99 | +| steal-deque | 23530 | 3.01× | 99 | +| asyncio.Queue | 53915 | 6.89× | 99 | +| queue.Queue | 66819 | 8.54× | 99 | +| janus | 128735 | 16.46× | 99 | diff --git a/experiments/13-payload-size-sweep/results.json b/experiments/13-payload-size-sweep/results.json new file mode 100644 index 0000000..821227a --- /dev/null +++ b/experiments/13-payload-size-sweep/results.json @@ -0,0 +1,3268 @@ +{ + "generated_at": "2026-09-01T22:23:00Z", + "question": "Which SPSC payload sizes change the ranking?", + "sizes_bytes": [ + 1, + 64, + 256, + 4096, + 65536 + ], + "baseline_bytes": 256, + "recommendation": { + "default_matrix": [ + { + "test_data": "size_256", + "payload_bytes": 256, + "why": [ + "baseline (pointer-bound / typical small message)" + ] + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "why": [ + "rust: copy-bound pack collapse (time \u00d79.24, spread 1.19\u00d7)" + ] + } + ], + "research": [ + { + "test_data": "size_65536", + "payload_bytes": 65536, + "why": [ + "rust: rank inversion (Spearman -0.357)", + "rust: first place crossbeam-queue -> std-mpsc and time \u00d7282.37" + ] + } + ], + "redundant": [ + { + "test_data": "size_1", + "payload_bytes": 1 + }, + { + "test_data": "size_64", + "payload_bytes": 64 + } + ], + "keep": [ + { + "test_data": "size_256", + "payload_bytes": 256, + "why": [ + "baseline (pointer-bound / typical small message)" + ] + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "why": [ + "rust: copy-bound pack collapse (time \u00d79.24, spread 1.19\u00d7)" + ] + } + ], + "drop": [ + { + "test_data": "size_1", + "payload_bytes": 1 + }, + { + "test_data": "size_64", + "payload_bytes": 64 + } + ], + "rule": "Keep 256 B as the default small cell. Add one larger cell only when some language becomes copy-bound (handoff at least 2\u00d7 and the pack collapses to about 1.3\u00d7) or the ranking inverts. Mid-pack swaps with a flat time scale are not a new size. A later inversion after the first copy-cost knee stays a research / experiment cell, not a third default type." + }, + "languages": { + "python": { + "status": "ok", + "rows": [ + { + "library": "queue.SimpleQueue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6360.0, + "total_median_ns": 6360.0, + "p50_ns": 6360.0, + "mean_ns": 6418.20202020202, + "enq_median_ns": 2735.0, + "write_median_ns": 2735.0, + "deq_median_ns": 3617.0, + "read_median_ns": 3617.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 15263.0, + "total_median_ns": 15263.0, + "p50_ns": 15263.0, + "mean_ns": 15604.868686868687, + "enq_median_ns": 7007.0, + "write_median_ns": 7007.0, + "deq_median_ns": 8289.0, + "read_median_ns": 8289.0, + "rel_to_fastest": 2.3998427672955973 + }, + { + "library": "deque-lock", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 18062.0, + "total_median_ns": 18062.0, + "p50_ns": 18062.0, + "mean_ns": 18166.80808080808, + "enq_median_ns": 8358.0, + "write_median_ns": 8358.0, + "deq_median_ns": 9706.0, + "read_median_ns": 9706.0, + "rel_to_fastest": 2.839937106918239 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 20020.0, + "total_median_ns": 20020.0, + "p50_ns": 20020.0, + "mean_ns": 20108.050505050505, + "enq_median_ns": 9357.0, + "write_median_ns": 9357.0, + "deq_median_ns": 10679.0, + "read_median_ns": 10679.0, + "rel_to_fastest": 3.147798742138365 + }, + { + "library": "asyncio.Queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43637.0, + "total_median_ns": 43637.0, + "p50_ns": 43637.0, + "mean_ns": 43774.16161616162, + "enq_median_ns": 25452.0, + "write_median_ns": 25452.0, + "deq_median_ns": 17911.0, + "read_median_ns": 17911.0, + "rel_to_fastest": 6.861163522012578 + }, + { + "library": "queue.Queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 52988.0, + "total_median_ns": 52988.0, + "p50_ns": 52988.0, + "mean_ns": 53485.818181818184, + "enq_median_ns": 27147.0, + "write_median_ns": 27147.0, + "deq_median_ns": 25599.0, + "read_median_ns": 25599.0, + "rel_to_fastest": 8.331446540880503 + }, + { + "library": "janus", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 105187.0, + "total_median_ns": 105187.0, + "p50_ns": 105187.0, + "mean_ns": 108440.06060606061, + "enq_median_ns": 55364.0, + "write_median_ns": 55364.0, + "deq_median_ns": 49556.0, + "read_median_ns": 49556.0, + "rel_to_fastest": 16.53883647798742 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6750.0, + "total_median_ns": 6750.0, + "p50_ns": 6750.0, + "mean_ns": 6807.858585858586, + "enq_median_ns": 3037.0, + "write_median_ns": 3037.0, + "deq_median_ns": 3719.0, + "read_median_ns": 3719.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 15177.0, + "total_median_ns": 15177.0, + "p50_ns": 15177.0, + "mean_ns": 15857.0, + "enq_median_ns": 6891.0, + "write_median_ns": 6891.0, + "deq_median_ns": 8335.0, + "read_median_ns": 8335.0, + "rel_to_fastest": 2.2484444444444445 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19446.0, + "total_median_ns": 19446.0, + "p50_ns": 19446.0, + "mean_ns": 19425.41414141414, + "enq_median_ns": 9013.0, + "write_median_ns": 9013.0, + "deq_median_ns": 10400.0, + "read_median_ns": 10400.0, + "rel_to_fastest": 2.880888888888889 + }, + { + "library": "deque-lock", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19924.0, + "total_median_ns": 19924.0, + "p50_ns": 19924.0, + "mean_ns": 19990.878787878788, + "enq_median_ns": 9146.0, + "write_median_ns": 9146.0, + "deq_median_ns": 10763.0, + "read_median_ns": 10763.0, + "rel_to_fastest": 2.9517037037037035 + }, + { + "library": "asyncio.Queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 45670.0, + "total_median_ns": 45670.0, + "p50_ns": 45670.0, + "mean_ns": 47104.93939393939, + "enq_median_ns": 26744.0, + "write_median_ns": 26744.0, + "deq_median_ns": 18637.0, + "read_median_ns": 18637.0, + "rel_to_fastest": 6.765925925925926 + }, + { + "library": "queue.Queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58876.0, + "total_median_ns": 58876.0, + "p50_ns": 58876.0, + "mean_ns": 59482.606060606064, + "enq_median_ns": 30292.0, + "write_median_ns": 30292.0, + "deq_median_ns": 28580.0, + "read_median_ns": 28580.0, + "rel_to_fastest": 8.72237037037037 + }, + { + "library": "janus", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 107444.0, + "total_median_ns": 107444.0, + "p50_ns": 107444.0, + "mean_ns": 110398.9898989899, + "enq_median_ns": 56786.0, + "write_median_ns": 56786.0, + "deq_median_ns": 50976.0, + "read_median_ns": 50976.0, + "rel_to_fastest": 15.91762962962963 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6755.0, + "total_median_ns": 6755.0, + "p50_ns": 6755.0, + "mean_ns": 6779.656565656565, + "enq_median_ns": 3027.0, + "write_median_ns": 3027.0, + "deq_median_ns": 3708.0, + "read_median_ns": 3708.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 16353.0, + "total_median_ns": 16353.0, + "p50_ns": 16353.0, + "mean_ns": 16807.757575757576, + "enq_median_ns": 7425.0, + "write_median_ns": 7425.0, + "deq_median_ns": 8947.0, + "read_median_ns": 8947.0, + "rel_to_fastest": 2.4208734270910437 + }, + { + "library": "deque-lock", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19305.0, + "total_median_ns": 19305.0, + "p50_ns": 19305.0, + "mean_ns": 19551.222222222223, + "enq_median_ns": 8919.0, + "write_median_ns": 8919.0, + "deq_median_ns": 10399.0, + "read_median_ns": 10399.0, + "rel_to_fastest": 2.857883049592894 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19920.0, + "total_median_ns": 19920.0, + "p50_ns": 19920.0, + "mean_ns": 20059.545454545456, + "enq_median_ns": 9298.0, + "write_median_ns": 9298.0, + "deq_median_ns": 10624.0, + "read_median_ns": 10624.0, + "rel_to_fastest": 2.9489267209474463 + }, + { + "library": "asyncio.Queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 46617.0, + "total_median_ns": 46617.0, + "p50_ns": 46617.0, + "mean_ns": 46869.42424242424, + "enq_median_ns": 27130.0, + "write_median_ns": 27130.0, + "deq_median_ns": 18850.0, + "read_median_ns": 18850.0, + "rel_to_fastest": 6.9011102886750555 + }, + { + "library": "queue.Queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58004.0, + "total_median_ns": 58004.0, + "p50_ns": 58004.0, + "mean_ns": 58470.59595959596, + "enq_median_ns": 29638.0, + "write_median_ns": 29638.0, + "deq_median_ns": 27958.0, + "read_median_ns": 27958.0, + "rel_to_fastest": 8.586824574389341 + }, + { + "library": "janus", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 110450.0, + "total_median_ns": 110450.0, + "p50_ns": 110450.0, + "mean_ns": 112215.77777777778, + "enq_median_ns": 58464.0, + "write_median_ns": 58464.0, + "deq_median_ns": 52660.0, + "read_median_ns": 52660.0, + "rel_to_fastest": 16.350851221317544 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7251.0, + "total_median_ns": 7251.0, + "p50_ns": 7251.0, + "mean_ns": 7245.989898989899, + "enq_median_ns": 3248.0, + "write_median_ns": 3248.0, + "deq_median_ns": 3991.0, + "read_median_ns": 3991.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 18716.0, + "total_median_ns": 18716.0, + "p50_ns": 18716.0, + "mean_ns": 18997.363636363636, + "enq_median_ns": 8489.0, + "write_median_ns": 8489.0, + "deq_median_ns": 10273.0, + "read_median_ns": 10273.0, + "rel_to_fastest": 2.5811612191421873 + }, + { + "library": "deque-lock", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19357.0, + "total_median_ns": 19357.0, + "p50_ns": 19357.0, + "mean_ns": 19652.838383838385, + "enq_median_ns": 8989.0, + "write_median_ns": 8989.0, + "deq_median_ns": 10348.0, + "read_median_ns": 10348.0, + "rel_to_fastest": 2.669562818921528 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 22783.0, + "total_median_ns": 22783.0, + "p50_ns": 22783.0, + "mean_ns": 22882.535353535353, + "enq_median_ns": 10585.0, + "write_median_ns": 10585.0, + "deq_median_ns": 12185.0, + "read_median_ns": 12185.0, + "rel_to_fastest": 3.142049372500345 + }, + { + "library": "asyncio.Queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 47305.0, + "total_median_ns": 47305.0, + "p50_ns": 47305.0, + "mean_ns": 47896.31313131313, + "enq_median_ns": 28566.0, + "write_median_ns": 28566.0, + "deq_median_ns": 18769.0, + "read_median_ns": 18769.0, + "rel_to_fastest": 6.523927734105641 + }, + { + "library": "queue.Queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 58309.0, + "total_median_ns": 58309.0, + "p50_ns": 58309.0, + "mean_ns": 58677.656565656565, + "enq_median_ns": 29925.0, + "write_median_ns": 29925.0, + "deq_median_ns": 28183.0, + "read_median_ns": 28183.0, + "rel_to_fastest": 8.041511515653013 + }, + { + "library": "janus", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 118035.0, + "total_median_ns": 118035.0, + "p50_ns": 118035.0, + "mean_ns": 121731.71717171717, + "enq_median_ns": 61966.0, + "write_median_ns": 61966.0, + "deq_median_ns": 55444.0, + "read_median_ns": 55444.0, + "rel_to_fastest": 16.278444352503104 + }, + { + "library": "queue.SimpleQueue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7821.0, + "total_median_ns": 7821.0, + "p50_ns": 7821.0, + "mean_ns": 7873.79797979798, + "enq_median_ns": 3493.0, + "write_median_ns": 3493.0, + "deq_median_ns": 4325.0, + "read_median_ns": 4325.0, + "rel_to_fastest": 1.0 + }, + { + "library": "spsc-ring", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 19707.0, + "total_median_ns": 19707.0, + "p50_ns": 19707.0, + "mean_ns": 20040.646464646463, + "enq_median_ns": 8954.0, + "write_median_ns": 8954.0, + "deq_median_ns": 10751.0, + "read_median_ns": 10751.0, + "rel_to_fastest": 2.5197545070962795 + }, + { + "library": "deque-lock", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 23091.0, + "total_median_ns": 23091.0, + "p50_ns": 23091.0, + "mean_ns": 23207.121212121212, + "enq_median_ns": 10747.0, + "write_median_ns": 10747.0, + "deq_median_ns": 12346.0, + "read_median_ns": 12346.0, + "rel_to_fastest": 2.9524357499041045 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 23530.0, + "total_median_ns": 23530.0, + "p50_ns": 23530.0, + "mean_ns": 23596.151515151516, + "enq_median_ns": 11054.0, + "write_median_ns": 11054.0, + "deq_median_ns": 12519.0, + "read_median_ns": 12519.0, + "rel_to_fastest": 3.0085666794527555 + }, + { + "library": "asyncio.Queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 53915.0, + "total_median_ns": 53915.0, + "p50_ns": 53915.0, + "mean_ns": 54091.979797979795, + "enq_median_ns": 31335.0, + "write_median_ns": 31335.0, + "deq_median_ns": 21617.0, + "read_median_ns": 21617.0, + "rel_to_fastest": 6.893619741721007 + }, + { + "library": "queue.Queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 66819.0, + "total_median_ns": 66819.0, + "p50_ns": 66819.0, + "mean_ns": 67272.19191919192, + "enq_median_ns": 34449.0, + "write_median_ns": 34449.0, + "deq_median_ns": 32220.0, + "read_median_ns": 32220.0, + "rel_to_fastest": 8.543536632144226 + }, + { + "library": "janus", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 128735.0, + "total_median_ns": 128735.0, + "p50_ns": 128735.0, + "mean_ns": 128821.04040404041, + "enq_median_ns": 67347.0, + "write_median_ns": 67347.0, + "deq_median_ns": 60493.0, + "read_median_ns": 60493.0, + "rel_to_fastest": 16.460171333589056 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 0.9360748224896497, + "spread": 16.53883647798742, + "n_libs": 7 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "steal-deque", + "deque-lock", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9642857142857142, + "kendall": 0.9047619047619048, + "flips": [ + "deque-lock vs steal-deque" + ], + "flip_count": 1, + "time_ratio_median": 0.9796855224488921, + "spread": 15.91762962962963, + "n_libs": 7 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 16.350851221317544, + "n_libs": 7 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.068673607967406, + "spread": 16.278444352503104, + "n_libs": 7 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "queue.SimpleQueue", + "spsc-ring", + "deque-lock", + "steal-deque", + "asyncio.Queue", + "queue.Queue", + "janus" + ], + "first": "queue.SimpleQueue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.1655500226346762, + "spread": 16.460171333589056, + "n_libs": 7 + } + ] + }, + "rust": { + "status": "ok", + "rows": [ + { + "library": "crossbeam-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4107.0, + "total_median_ns": 4107.0, + "p50_ns": 4107.0, + "mean_ns": 4161.030303030303, + "enq_median_ns": 2314.0, + "write_median_ns": 2314.0, + "deq_median_ns": 1795.0, + "read_median_ns": 1795.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4425.0, + "total_median_ns": 4425.0, + "p50_ns": 4425.0, + "mean_ns": 4558.010101010101, + "enq_median_ns": 2521.0, + "write_median_ns": 2521.0, + "deq_median_ns": 1905.0, + "read_median_ns": 1905.0, + "rel_to_fastest": 1.0774287801314828 + }, + { + "library": "flume", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6472.0, + "total_median_ns": 6472.0, + "p50_ns": 6472.0, + "mean_ns": 6530.545454545455, + "enq_median_ns": 3163.0, + "write_median_ns": 3163.0, + "deq_median_ns": 3308.0, + "read_median_ns": 3308.0, + "rel_to_fastest": 1.5758461163866568 + }, + { + "library": "crossbeam-channel", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6834.0, + "total_median_ns": 6834.0, + "p50_ns": 6834.0, + "mean_ns": 6919.717171717171, + "enq_median_ns": 3373.0, + "write_median_ns": 3373.0, + "deq_median_ns": 3471.0, + "read_median_ns": 3471.0, + "rel_to_fastest": 1.6639883126369612 + }, + { + "library": "tokio-mpsc", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7745.0, + "total_median_ns": 7745.0, + "p50_ns": 7745.0, + "mean_ns": 7771.171717171717, + "enq_median_ns": 4835.0, + "write_median_ns": 4835.0, + "deq_median_ns": 2909.0, + "read_median_ns": 2909.0, + "rel_to_fastest": 1.8858047236425615 + }, + { + "library": "std-mpsc", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9546.0, + "total_median_ns": 9546.0, + "p50_ns": 9546.0, + "mean_ns": 8903.676767676769, + "enq_median_ns": 5311.0, + "write_median_ns": 5311.0, + "deq_median_ns": 4000.0, + "read_median_ns": 4000.0, + "rel_to_fastest": 2.324324324324324 + }, + { + "library": "async-channel", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 10470.0, + "total_median_ns": 10470.0, + "p50_ns": 10470.0, + "mean_ns": 11423.161616161617, + "enq_median_ns": 6293.0, + "write_median_ns": 6293.0, + "deq_median_ns": 4250.0, + "read_median_ns": 4250.0, + "rel_to_fastest": 2.5493060628195763 + }, + { + "library": "crossbeam-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4542.0, + "total_median_ns": 4542.0, + "p50_ns": 4542.0, + "mean_ns": 4667.474747474747, + "enq_median_ns": 2652.0, + "write_median_ns": 2652.0, + "deq_median_ns": 1889.0, + "read_median_ns": 1889.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4601.0, + "total_median_ns": 4601.0, + "p50_ns": 4601.0, + "mean_ns": 4629.909090909091, + "enq_median_ns": 2601.0, + "write_median_ns": 2601.0, + "deq_median_ns": 2004.0, + "read_median_ns": 2004.0, + "rel_to_fastest": 1.0129898723029502 + }, + { + "library": "flume", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4887.0, + "total_median_ns": 4887.0, + "p50_ns": 4887.0, + "mean_ns": 4965.818181818182, + "enq_median_ns": 2478.0, + "write_median_ns": 2478.0, + "deq_median_ns": 2412.0, + "read_median_ns": 2412.0, + "rel_to_fastest": 1.0759577278731836 + }, + { + "library": "std-mpsc", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4902.0, + "total_median_ns": 4902.0, + "p50_ns": 4902.0, + "mean_ns": 4932.434343434344, + "enq_median_ns": 2922.0, + "write_median_ns": 2922.0, + "deq_median_ns": 1991.0, + "read_median_ns": 1991.0, + "rel_to_fastest": 1.0792602377807134 + }, + { + "library": "crossbeam-channel", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5634.0, + "total_median_ns": 5634.0, + "p50_ns": 5634.0, + "mean_ns": 5665.818181818182, + "enq_median_ns": 2888.0, + "write_median_ns": 2888.0, + "deq_median_ns": 2759.0, + "read_median_ns": 2759.0, + "rel_to_fastest": 1.2404227212681638 + }, + { + "library": "tokio-mpsc", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6164.0, + "total_median_ns": 6164.0, + "p50_ns": 6164.0, + "mean_ns": 6192.717171717171, + "enq_median_ns": 4182.0, + "write_median_ns": 4182.0, + "deq_median_ns": 1992.0, + "read_median_ns": 1992.0, + "rel_to_fastest": 1.3571114046675474 + }, + { + "library": "async-channel", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 10891.0, + "total_median_ns": 10891.0, + "p50_ns": 10891.0, + "mean_ns": 10925.20202020202, + "enq_median_ns": 6589.0, + "write_median_ns": 6589.0, + "deq_median_ns": 4284.0, + "read_median_ns": 4284.0, + "rel_to_fastest": 2.397842360193747 + }, + { + "library": "crossbeam-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5350.0, + "total_median_ns": 5350.0, + "p50_ns": 5350.0, + "mean_ns": 5405.656565656565, + "enq_median_ns": 2931.0, + "write_median_ns": 2931.0, + "deq_median_ns": 2424.0, + "read_median_ns": 2424.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5446.0, + "total_median_ns": 5446.0, + "p50_ns": 5446.0, + "mean_ns": 5504.393939393939, + "enq_median_ns": 2960.0, + "write_median_ns": 2960.0, + "deq_median_ns": 2498.0, + "read_median_ns": 2498.0, + "rel_to_fastest": 1.0179439252336449 + }, + { + "library": "std-mpsc", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6019.0, + "total_median_ns": 6019.0, + "p50_ns": 6019.0, + "mean_ns": 5936.575757575758, + "enq_median_ns": 3376.0, + "write_median_ns": 3376.0, + "deq_median_ns": 2632.0, + "read_median_ns": 2632.0, + "rel_to_fastest": 1.1250467289719626 + }, + { + "library": "flume", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6546.0, + "total_median_ns": 6546.0, + "p50_ns": 6546.0, + "mean_ns": 6656.929292929293, + "enq_median_ns": 3396.0, + "write_median_ns": 3396.0, + "deq_median_ns": 3155.0, + "read_median_ns": 3155.0, + "rel_to_fastest": 1.223551401869159 + }, + { + "library": "crossbeam-channel", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6762.0, + "total_median_ns": 6762.0, + "p50_ns": 6762.0, + "mean_ns": 6824.181818181818, + "enq_median_ns": 3326.0, + "write_median_ns": 3326.0, + "deq_median_ns": 3436.0, + "read_median_ns": 3436.0, + "rel_to_fastest": 1.2639252336448599 + }, + { + "library": "tokio-mpsc", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7304.0, + "total_median_ns": 7304.0, + "p50_ns": 7304.0, + "mean_ns": 7214.979797979798, + "enq_median_ns": 4663.0, + "write_median_ns": 4663.0, + "deq_median_ns": 2609.0, + "read_median_ns": 2609.0, + "rel_to_fastest": 1.365233644859813 + }, + { + "library": "async-channel", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 11474.0, + "total_median_ns": 11474.0, + "p50_ns": 11474.0, + "mean_ns": 11723.29292929293, + "enq_median_ns": 6702.0, + "write_median_ns": 6702.0, + "deq_median_ns": 4776.0, + "read_median_ns": 4776.0, + "rel_to_fastest": 2.1446728971962616 + }, + { + "library": "flume", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 59130.0, + "total_median_ns": 59130.0, + "p50_ns": 59130.0, + "mean_ns": 62223.84848484849, + "enq_median_ns": 53549.0, + "write_median_ns": 53549.0, + "deq_median_ns": 5416.0, + "read_median_ns": 5416.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 59582.0, + "total_median_ns": 59582.0, + "p50_ns": 59582.0, + "mean_ns": 61626.09090909091, + "enq_median_ns": 54037.0, + "write_median_ns": 54037.0, + "deq_median_ns": 5518.0, + "read_median_ns": 5518.0, + "rel_to_fastest": 1.0076441738542194 + }, + { + "library": "crossbeam-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 61833.0, + "total_median_ns": 61833.0, + "p50_ns": 61833.0, + "mean_ns": 64398.35353535353, + "enq_median_ns": 51876.0, + "write_median_ns": 51876.0, + "deq_median_ns": 9879.0, + "read_median_ns": 9879.0, + "rel_to_fastest": 1.045712836123795 + }, + { + "library": "std-mpsc", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62230.0, + "total_median_ns": 62230.0, + "p50_ns": 62230.0, + "mean_ns": 63522.080808080806, + "enq_median_ns": 52231.0, + "write_median_ns": 52231.0, + "deq_median_ns": 9842.0, + "read_median_ns": 9842.0, + "rel_to_fastest": 1.0524268560798242 + }, + { + "library": "crossbeam-channel", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62478.0, + "total_median_ns": 62478.0, + "p50_ns": 62478.0, + "mean_ns": 64050.77777777778, + "enq_median_ns": 51740.0, + "write_median_ns": 51740.0, + "deq_median_ns": 10571.0, + "read_median_ns": 10571.0, + "rel_to_fastest": 1.05662100456621 + }, + { + "library": "tokio-mpsc", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 65210.0, + "total_median_ns": 65210.0, + "p50_ns": 65210.0, + "mean_ns": 68044.23232323233, + "enq_median_ns": 54640.0, + "write_median_ns": 54640.0, + "deq_median_ns": 10282.0, + "read_median_ns": 10282.0, + "rel_to_fastest": 1.1028242854726873 + }, + { + "library": "async-channel", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 70093.0, + "total_median_ns": 70093.0, + "p50_ns": 70093.0, + "mean_ns": 73494.11111111111, + "enq_median_ns": 57328.0, + "write_median_ns": 57328.0, + "deq_median_ns": 12708.0, + "read_median_ns": 12708.0, + "rel_to_fastest": 1.1854050397429392 + }, + { + "library": "std-mpsc", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1564000.0, + "total_median_ns": 1564000.0, + "p50_ns": 1564000.0, + "mean_ns": 1732242.4141414142, + "enq_median_ns": 1438754.0, + "write_median_ns": 1438754.0, + "deq_median_ns": 121465.0, + "read_median_ns": 121465.0, + "rel_to_fastest": 1.0 + }, + { + "library": "crossbeam-channel", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1755998.0, + "total_median_ns": 1755998.0, + "p50_ns": 1755998.0, + "mean_ns": 1844903.9696969697, + "enq_median_ns": 1620795.0, + "write_median_ns": 1620795.0, + "deq_median_ns": 128929.0, + "read_median_ns": 128929.0, + "rel_to_fastest": 1.1227608695652174 + }, + { + "library": "flume", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1944333.0, + "total_median_ns": 1944333.0, + "p50_ns": 1944333.0, + "mean_ns": 2090790.3333333333, + "enq_median_ns": 1808146.0, + "write_median_ns": 1808146.0, + "deq_median_ns": 152019.0, + "read_median_ns": 152019.0, + "rel_to_fastest": 1.2431796675191815 + }, + { + "library": "async-channel", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1963145.0, + "total_median_ns": 1963145.0, + "p50_ns": 1963145.0, + "mean_ns": 2044139.8484848484, + "enq_median_ns": 1803408.0, + "write_median_ns": 1803408.0, + "deq_median_ns": 160831.0, + "read_median_ns": 160831.0, + "rel_to_fastest": 1.255207800511509 + }, + { + "library": "tokio-mpsc", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2062398.0, + "total_median_ns": 2062398.0, + "p50_ns": 2062398.0, + "mean_ns": 2149374.8585858587, + "enq_median_ns": 1905632.0, + "write_median_ns": 1905632.0, + "deq_median_ns": 157634.0, + "read_median_ns": 157634.0, + "rel_to_fastest": 1.3186687979539642 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2096368.0, + "total_median_ns": 2096368.0, + "p50_ns": 2096368.0, + "mean_ns": 2164774.606060606, + "enq_median_ns": 1945730.0, + "write_median_ns": 1945730.0, + "deq_median_ns": 157651.0, + "read_median_ns": 157651.0, + "rel_to_fastest": 1.340388746803069 + }, + { + "library": "crossbeam-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2113792.0, + "total_median_ns": 2113792.0, + "p50_ns": 2113792.0, + "mean_ns": 2213570.8282828284, + "enq_median_ns": 1960205.0, + "write_median_ns": 1960205.0, + "deq_median_ns": 159693.0, + "read_median_ns": 159693.0, + "rel_to_fastest": 1.3515294117647059 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "crossbeam-queue", + "steal-deque", + "flume", + "crossbeam-channel", + "tokio-mpsc", + "std-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.7857142857142856, + "kendall": 0.7142857142857143, + "flips": [ + "std-mpsc vs flume", + "std-mpsc vs crossbeam-channel", + "std-mpsc vs tokio-mpsc" + ], + "flip_count": 3, + "time_ratio_median": 0.9886953864955698, + "spread": 2.5493060628195763, + "n_libs": 7 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "crossbeam-queue", + "steal-deque", + "flume", + "std-mpsc", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.9642857142857142, + "kendall": 0.9047619047619048, + "flips": [ + "std-mpsc vs flume" + ], + "flip_count": 1, + "time_ratio_median": 0.843921139101862, + "spread": 2.397842360193747, + "n_libs": 7 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "crossbeam-queue", + "steal-deque", + "std-mpsc", + "flume", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 2.1446728971962616, + "n_libs": 7 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "flume", + "steal-deque", + "crossbeam-queue", + "std-mpsc", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "flume", + "spearman": 0.7499999999999999, + "kendall": 0.6190476190476191, + "flips": [ + "crossbeam-queue vs steal-deque", + "crossbeam-queue vs flume", + "steal-deque vs flume", + "std-mpsc vs flume" + ], + "flip_count": 4, + "time_ratio_median": 9.239574090505768, + "spread": 1.1854050397429392, + "n_libs": 7 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "std-mpsc", + "crossbeam-channel", + "flume", + "async-channel", + "tokio-mpsc", + "steal-deque", + "crossbeam-queue" + ], + "first": "std-mpsc", + "spearman": -0.3571428571428571, + "kendall": -0.23809523809523808, + "flips": [ + "crossbeam-queue vs steal-deque", + "crossbeam-queue vs std-mpsc", + "crossbeam-queue vs flume", + "crossbeam-queue vs crossbeam-channel", + "crossbeam-queue vs tokio-mpsc", + "crossbeam-queue vs async-channel", + "steal-deque vs std-mpsc", + "steal-deque vs flume", + "steal-deque vs crossbeam-channel", + "steal-deque vs tokio-mpsc", + "steal-deque vs async-channel", + "flume vs crossbeam-channel", + "tokio-mpsc vs async-channel" + ], + "flip_count": 13, + "time_ratio_median": 282.3655531215772, + "spread": 1.3515294117647059, + "n_libs": 7 + } + ] + }, + "javascript": { + "status": "ok", + "rows": [ + { + "library": "fastq", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1473.0, + "total_median_ns": 1473.0, + "p50_ns": 1473.0, + "mean_ns": 2441.2323232323233, + "enq_median_ns": 1473.0, + "write_median_ns": 1473.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3539.0, + "total_median_ns": 3539.0, + "p50_ns": 3539.0, + "mean_ns": 7782.585858585859, + "enq_median_ns": 2259.0, + "write_median_ns": 2259.0, + "deq_median_ns": 1307.0, + "read_median_ns": 1307.0, + "rel_to_fastest": 2.4025797691785473 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6797.0, + "total_median_ns": 6797.0, + "p50_ns": 6797.0, + "mean_ns": 5479.606060606061, + "enq_median_ns": 3056.0, + "write_median_ns": 3056.0, + "deq_median_ns": 3696.0, + "read_median_ns": 3696.0, + "rel_to_fastest": 4.61439239646979 + }, + { + "library": "yocto-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7600.0, + "total_median_ns": 7600.0, + "p50_ns": 7600.0, + "mean_ns": 10208.030303030304, + "enq_median_ns": 3549.0, + "write_median_ns": 3549.0, + "deq_median_ns": 4002.0, + "read_median_ns": 4002.0, + "rel_to_fastest": 5.159538357094365 + }, + { + "library": "Array", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8629.0, + "total_median_ns": 8629.0, + "p50_ns": 8629.0, + "mean_ns": 16840.757575757576, + "enq_median_ns": 4489.0, + "write_median_ns": 4489.0, + "deq_median_ns": 3862.0, + "read_median_ns": 3862.0, + "rel_to_fastest": 5.858112695179905 + }, + { + "library": "p-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 60642.0, + "total_median_ns": 60642.0, + "p50_ns": 60642.0, + "mean_ns": 84921.41414141415, + "enq_median_ns": 55802.0, + "write_median_ns": 55802.0, + "deq_median_ns": 4863.0, + "read_median_ns": 4863.0, + "rel_to_fastest": 41.169042769857434 + }, + { + "library": "fastq", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1388.0, + "total_median_ns": 1388.0, + "p50_ns": 1388.0, + "mean_ns": 1489.030303030303, + "enq_median_ns": 1388.0, + "write_median_ns": 1388.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Array", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2520.0, + "total_median_ns": 2520.0, + "p50_ns": 2520.0, + "mean_ns": 2825.131313131313, + "enq_median_ns": 806.0, + "write_median_ns": 806.0, + "deq_median_ns": 1715.0, + "read_median_ns": 1715.0, + "rel_to_fastest": 1.8155619596541788 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2811.0, + "total_median_ns": 2811.0, + "p50_ns": 2811.0, + "mean_ns": 2928.3636363636365, + "enq_median_ns": 974.0, + "write_median_ns": 974.0, + "deq_median_ns": 1829.0, + "read_median_ns": 1829.0, + "rel_to_fastest": 2.0252161383285303 + }, + { + "library": "denque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3094.0, + "total_median_ns": 3094.0, + "p50_ns": 3094.0, + "mean_ns": 6515.131313131313, + "enq_median_ns": 1768.0, + "write_median_ns": 1768.0, + "deq_median_ns": 1296.0, + "read_median_ns": 1296.0, + "rel_to_fastest": 2.229106628242075 + }, + { + "library": "yocto-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3477.0, + "total_median_ns": 3477.0, + "p50_ns": 3477.0, + "mean_ns": 4669.636363636364, + "enq_median_ns": 1677.0, + "write_median_ns": 1677.0, + "deq_median_ns": 1792.0, + "read_median_ns": 1792.0, + "rel_to_fastest": 2.505043227665706 + }, + { + "library": "p-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62336.0, + "total_median_ns": 62336.0, + "p50_ns": 62336.0, + "mean_ns": 89398.06060606061, + "enq_median_ns": 57891.0, + "write_median_ns": 57891.0, + "deq_median_ns": 4277.0, + "read_median_ns": 4277.0, + "rel_to_fastest": 44.91066282420749 + }, + { + "library": "fastq", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1404.0, + "total_median_ns": 1404.0, + "p50_ns": 1404.0, + "mean_ns": 1722.939393939394, + "enq_median_ns": 1404.0, + "write_median_ns": 1404.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2680.0, + "total_median_ns": 2680.0, + "p50_ns": 2680.0, + "mean_ns": 2743.40404040404, + "enq_median_ns": 1578.0, + "write_median_ns": 1578.0, + "deq_median_ns": 1108.0, + "read_median_ns": 1108.0, + "rel_to_fastest": 1.9088319088319088 + }, + { + "library": "Array", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2697.0, + "total_median_ns": 2697.0, + "p50_ns": 2697.0, + "mean_ns": 2718.5858585858587, + "enq_median_ns": 897.0, + "write_median_ns": 897.0, + "deq_median_ns": 1793.0, + "read_median_ns": 1793.0, + "rel_to_fastest": 1.920940170940171 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2980.0, + "total_median_ns": 2980.0, + "p50_ns": 2980.0, + "mean_ns": 3878.2020202020203, + "enq_median_ns": 1009.0, + "write_median_ns": 1009.0, + "deq_median_ns": 1976.0, + "read_median_ns": 1976.0, + "rel_to_fastest": 2.1225071225071224 + }, + { + "library": "yocto-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3556.0, + "total_median_ns": 3556.0, + "p50_ns": 3556.0, + "mean_ns": 4644.89898989899, + "enq_median_ns": 1736.0, + "write_median_ns": 1736.0, + "deq_median_ns": 1837.0, + "read_median_ns": 1837.0, + "rel_to_fastest": 2.532763532763533 + }, + { + "library": "p-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 45134.0, + "total_median_ns": 45134.0, + "p50_ns": 45134.0, + "mean_ns": 60979.606060606064, + "enq_median_ns": 41557.0, + "write_median_ns": 41557.0, + "deq_median_ns": 3615.0, + "read_median_ns": 3615.0, + "rel_to_fastest": 32.14672364672364 + }, + { + "library": "fastq", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1200.0, + "total_median_ns": 1200.0, + "p50_ns": 1200.0, + "mean_ns": 1311.8181818181818, + "enq_median_ns": 1200.0, + "write_median_ns": 1200.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "denque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2839.0, + "total_median_ns": 2839.0, + "p50_ns": 2839.0, + "mean_ns": 2891.6060606060605, + "enq_median_ns": 1653.0, + "write_median_ns": 1653.0, + "deq_median_ns": 1182.0, + "read_median_ns": 1182.0, + "rel_to_fastest": 2.3658333333333332 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2839.0, + "total_median_ns": 2839.0, + "p50_ns": 2839.0, + "mean_ns": 2913.070707070707, + "enq_median_ns": 939.0, + "write_median_ns": 939.0, + "deq_median_ns": 1902.0, + "read_median_ns": 1902.0, + "rel_to_fastest": 2.3658333333333332 + }, + { + "library": "Array", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2941.0, + "total_median_ns": 2941.0, + "p50_ns": 2941.0, + "mean_ns": 2987.030303030303, + "enq_median_ns": 987.0, + "write_median_ns": 987.0, + "deq_median_ns": 1952.0, + "read_median_ns": 1952.0, + "rel_to_fastest": 2.450833333333333 + }, + { + "library": "yocto-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3654.0, + "total_median_ns": 3654.0, + "p50_ns": 3654.0, + "mean_ns": 6775.888888888889, + "enq_median_ns": 1779.0, + "write_median_ns": 1779.0, + "deq_median_ns": 1861.0, + "read_median_ns": 1861.0, + "rel_to_fastest": 3.045 + }, + { + "library": "p-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43584.0, + "total_median_ns": 43584.0, + "p50_ns": 43584.0, + "mean_ns": 53845.15151515151, + "enq_median_ns": 40070.0, + "write_median_ns": 40070.0, + "deq_median_ns": 3551.0, + "read_median_ns": 3551.0, + "rel_to_fastest": 36.32 + }, + { + "library": "fastq", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1233.0, + "total_median_ns": 1233.0, + "p50_ns": 1233.0, + "mean_ns": 1354.1515151515152, + "enq_median_ns": 1233.0, + "write_median_ns": 1233.0, + "deq_median_ns": 0.0, + "read_median_ns": 0.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2825.0, + "total_median_ns": 2825.0, + "p50_ns": 2825.0, + "mean_ns": 2846.3333333333335, + "enq_median_ns": 880.0, + "write_median_ns": 880.0, + "deq_median_ns": 1926.0, + "read_median_ns": 1926.0, + "rel_to_fastest": 2.291159772911598 + }, + { + "library": "Array", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2985.0, + "total_median_ns": 2985.0, + "p50_ns": 2985.0, + "mean_ns": 3039.959595959596, + "enq_median_ns": 982.0, + "write_median_ns": 982.0, + "deq_median_ns": 1987.0, + "read_median_ns": 1987.0, + "rel_to_fastest": 2.420924574209246 + }, + { + "library": "denque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3043.0, + "total_median_ns": 3043.0, + "p50_ns": 3043.0, + "mean_ns": 3080.4242424242425, + "enq_median_ns": 1788.0, + "write_median_ns": 1788.0, + "deq_median_ns": 1239.0, + "read_median_ns": 1239.0, + "rel_to_fastest": 2.467964314679643 + }, + { + "library": "yocto-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3674.0, + "total_median_ns": 3674.0, + "p50_ns": 3674.0, + "mean_ns": 6320.363636363636, + "enq_median_ns": 1776.0, + "write_median_ns": 1776.0, + "deq_median_ns": 1888.0, + "read_median_ns": 1888.0, + "rel_to_fastest": 2.9797242497972425 + }, + { + "library": "p-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 43742.0, + "total_median_ns": 43742.0, + "p50_ns": 43742.0, + "mean_ns": 51323.0404040404, + "enq_median_ns": 40151.0, + "write_median_ns": 40151.0, + "deq_median_ns": 3537.0, + "read_median_ns": 3537.0, + "rel_to_fastest": 35.47607461476075 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "fastq", + "denque", + "steal-deque", + "yocto-queue", + "Array", + "p-queue" + ], + "first": "fastq", + "spearman": 0.8285714285714286, + "kendall": 0.7333333333333333, + "flips": [ + "Array vs steal-deque", + "Array vs yocto-queue" + ], + "flip_count": 2, + "time_ratio_median": 2.137232845894263, + "spread": 41.169042769857434, + "n_libs": 6 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "fastq", + "Array", + "steal-deque", + "denque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.8285714285714286, + "kendall": 0.7333333333333333, + "flips": [ + "denque vs Array", + "denque vs steal-deque" + ], + "flip_count": 2, + "time_ratio_median": 0.9886039886039886, + "spread": 44.91066282420749, + "n_libs": 6 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "fastq", + "denque", + "Array", + "steal-deque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 1.0, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 32.14672364672364, + "n_libs": 6 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "fastq", + "denque", + "steal-deque", + "Array", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.898645105261295, + "kendall": 0.8571428571428571, + "flips": [ + "Array vs steal-deque" + ], + "flip_count": 1, + "time_ratio_median": 1.0275590551181102, + "spread": 36.32, + "n_libs": 6 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "fastq", + "steal-deque", + "Array", + "denque", + "yocto-queue", + "p-queue" + ], + "first": "fastq", + "spearman": 0.7714285714285715, + "kendall": 0.6, + "flips": [ + "denque vs Array", + "denque vs steal-deque", + "Array vs steal-deque" + ], + "flip_count": 3, + "time_ratio_median": 1.0331833520809899, + "spread": 35.47607461476075, + "n_libs": 6 + } + ] + }, + "csharp": { + "status": "ok", + "rows": [ + { + "library": "ConcurrentQueue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3000.0, + "total_median_ns": 3000.0, + "p50_ns": 3000.0, + "mean_ns": 3834.343434343434, + "enq_median_ns": 1600.0, + "write_median_ns": 1600.0, + "deq_median_ns": 1200.0, + "read_median_ns": 1200.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Queue+lock", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5900.0, + "total_median_ns": 5900.0, + "p50_ns": 5900.0, + "mean_ns": 6696.969696969697, + "enq_median_ns": 3100.0, + "write_median_ns": 3100.0, + "deq_median_ns": 2700.0, + "read_median_ns": 2700.0, + "rel_to_fastest": 1.9666666666666666 + }, + { + "library": "BlockingCollection", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9200.0, + "total_median_ns": 9200.0, + "p50_ns": 9200.0, + "mean_ns": 9945.454545454546, + "enq_median_ns": 4400.0, + "write_median_ns": 4400.0, + "deq_median_ns": 4500.0, + "read_median_ns": 4500.0, + "rel_to_fastest": 3.066666666666667 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9400.0, + "total_median_ns": 9400.0, + "p50_ns": 9400.0, + "mean_ns": 9286.868686868687, + "enq_median_ns": 5900.0, + "write_median_ns": 5900.0, + "deq_median_ns": 3400.0, + "read_median_ns": 3400.0, + "rel_to_fastest": 3.1333333333333333 + }, + { + "library": "Channel", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 12200.0, + "total_median_ns": 12200.0, + "p50_ns": 12200.0, + "mean_ns": 13558.585858585859, + "enq_median_ns": 4800.0, + "write_median_ns": 4800.0, + "deq_median_ns": 6900.0, + "read_median_ns": 6900.0, + "rel_to_fastest": 4.066666666666666 + }, + { + "library": "ConcurrentQueue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 3100.0, + "total_median_ns": 3100.0, + "p50_ns": 3100.0, + "mean_ns": 3157.5757575757575, + "enq_median_ns": 1700.0, + "write_median_ns": 1700.0, + "deq_median_ns": 1400.0, + "read_median_ns": 1400.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Queue+lock", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7400.0, + "total_median_ns": 7400.0, + "p50_ns": 7400.0, + "mean_ns": 7710.10101010101, + "enq_median_ns": 4000.0, + "write_median_ns": 4000.0, + "deq_median_ns": 3300.0, + "read_median_ns": 3300.0, + "rel_to_fastest": 2.3870967741935485 + }, + { + "library": "BlockingCollection", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9600.0, + "total_median_ns": 9600.0, + "p50_ns": 9600.0, + "mean_ns": 9719.191919191919, + "enq_median_ns": 4400.0, + "write_median_ns": 4400.0, + "deq_median_ns": 5100.0, + "read_median_ns": 5100.0, + "rel_to_fastest": 3.096774193548387 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9900.0, + "total_median_ns": 9900.0, + "p50_ns": 9900.0, + "mean_ns": 9875.757575757576, + "enq_median_ns": 5100.0, + "write_median_ns": 5100.0, + "deq_median_ns": 4800.0, + "read_median_ns": 4800.0, + "rel_to_fastest": 3.193548387096774 + }, + { + "library": "Channel", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 12500.0, + "total_median_ns": 12500.0, + "p50_ns": 12500.0, + "mean_ns": 12627.272727272728, + "enq_median_ns": 4900.0, + "write_median_ns": 4900.0, + "deq_median_ns": 7600.0, + "read_median_ns": 7600.0, + "rel_to_fastest": 4.032258064516129 + }, + { + "library": "ConcurrentQueue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2900.0, + "total_median_ns": 2900.0, + "p50_ns": 2900.0, + "mean_ns": 2861.6161616161617, + "enq_median_ns": 1600.0, + "write_median_ns": 1600.0, + "deq_median_ns": 1200.0, + "read_median_ns": 1200.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Queue+lock", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6200.0, + "total_median_ns": 6200.0, + "p50_ns": 6200.0, + "mean_ns": 6230.30303030303, + "enq_median_ns": 3500.0, + "write_median_ns": 3500.0, + "deq_median_ns": 2700.0, + "read_median_ns": 2700.0, + "rel_to_fastest": 2.1379310344827585 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8900.0, + "total_median_ns": 8900.0, + "p50_ns": 8900.0, + "mean_ns": 8957.575757575758, + "enq_median_ns": 4900.0, + "write_median_ns": 4900.0, + "deq_median_ns": 4000.0, + "read_median_ns": 4000.0, + "rel_to_fastest": 3.0689655172413794 + }, + { + "library": "BlockingCollection", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9100.0, + "total_median_ns": 9100.0, + "p50_ns": 9100.0, + "mean_ns": 9284.848484848484, + "enq_median_ns": 4200.0, + "write_median_ns": 4200.0, + "deq_median_ns": 4800.0, + "read_median_ns": 4800.0, + "rel_to_fastest": 3.1379310344827585 + }, + { + "library": "Channel", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 12200.0, + "total_median_ns": 12200.0, + "p50_ns": 12200.0, + "mean_ns": 12381.818181818182, + "enq_median_ns": 4700.0, + "write_median_ns": 4700.0, + "deq_median_ns": 7300.0, + "read_median_ns": 7300.0, + "rel_to_fastest": 4.206896551724138 + }, + { + "library": "ConcurrentQueue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2600.0, + "total_median_ns": 2600.0, + "p50_ns": 2600.0, + "mean_ns": 2664.6464646464647, + "enq_median_ns": 1400.0, + "write_median_ns": 1400.0, + "deq_median_ns": 1100.0, + "read_median_ns": 1100.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Queue+lock", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5100.0, + "total_median_ns": 5100.0, + "p50_ns": 5100.0, + "mean_ns": 5683.838383838384, + "enq_median_ns": 3000.0, + "write_median_ns": 3000.0, + "deq_median_ns": 2200.0, + "read_median_ns": 2200.0, + "rel_to_fastest": 1.9615384615384615 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8100.0, + "total_median_ns": 8100.0, + "p50_ns": 8100.0, + "mean_ns": 8143.434343434344, + "enq_median_ns": 4600.0, + "write_median_ns": 4600.0, + "deq_median_ns": 3400.0, + "read_median_ns": 3400.0, + "rel_to_fastest": 3.1153846153846154 + }, + { + "library": "BlockingCollection", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8900.0, + "total_median_ns": 8900.0, + "p50_ns": 8900.0, + "mean_ns": 8960.60606060606, + "enq_median_ns": 4200.0, + "write_median_ns": 4200.0, + "deq_median_ns": 4600.0, + "read_median_ns": 4600.0, + "rel_to_fastest": 3.423076923076923 + }, + { + "library": "Channel", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 12000.0, + "total_median_ns": 12000.0, + "p50_ns": 12000.0, + "mean_ns": 12141.414141414141, + "enq_median_ns": 4600.0, + "write_median_ns": 4600.0, + "deq_median_ns": 7300.0, + "read_median_ns": 7300.0, + "rel_to_fastest": 4.615384615384615 + }, + { + "library": "ConcurrentQueue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2800.0, + "total_median_ns": 2800.0, + "p50_ns": 2800.0, + "mean_ns": 3188.8888888888887, + "enq_median_ns": 1700.0, + "write_median_ns": 1700.0, + "deq_median_ns": 1100.0, + "read_median_ns": 1100.0, + "rel_to_fastest": 1.0 + }, + { + "library": "Queue+lock", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4900.0, + "total_median_ns": 4900.0, + "p50_ns": 4900.0, + "mean_ns": 5037.373737373738, + "enq_median_ns": 2800.0, + "write_median_ns": 2800.0, + "deq_median_ns": 2100.0, + "read_median_ns": 2100.0, + "rel_to_fastest": 1.75 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 8700.0, + "total_median_ns": 8700.0, + "p50_ns": 8700.0, + "mean_ns": 9273.737373737375, + "enq_median_ns": 5000.0, + "write_median_ns": 5000.0, + "deq_median_ns": 3800.0, + "read_median_ns": 3800.0, + "rel_to_fastest": 3.107142857142857 + }, + { + "library": "BlockingCollection", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 10800.0, + "total_median_ns": 10800.0, + "p50_ns": 10800.0, + "mean_ns": 11419.191919191919, + "enq_median_ns": 4700.0, + "write_median_ns": 4700.0, + "deq_median_ns": 5900.0, + "read_median_ns": 5900.0, + "rel_to_fastest": 3.857142857142857 + }, + { + "library": "Channel", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 17500.0, + "total_median_ns": 17500.0, + "p50_ns": 17500.0, + "mean_ns": 17896.969696969696, + "enq_median_ns": 6100.0, + "write_median_ns": 6100.0, + "deq_median_ns": 11300.0, + "read_median_ns": 11300.0, + "rel_to_fastest": 6.25 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "ConcurrentQueue", + "Queue+lock", + "BlockingCollection", + "steal-deque", + "Channel" + ], + "first": "ConcurrentQueue", + "spearman": 0.8999999999999998, + "kendall": 0.8, + "flips": [ + "steal-deque vs BlockingCollection" + ], + "flip_count": 1, + "time_ratio_median": 1.010989010989011, + "spread": 4.066666666666666, + "n_libs": 5 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "ConcurrentQueue", + "Queue+lock", + "BlockingCollection", + "steal-deque", + "Channel" + ], + "first": "ConcurrentQueue", + "spearman": 0.8999999999999998, + "kendall": 0.8, + "flips": [ + "steal-deque vs BlockingCollection" + ], + "flip_count": 1, + "time_ratio_median": 1.0689655172413792, + "spread": 4.032258064516129, + "n_libs": 5 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "ConcurrentQueue", + "Queue+lock", + "steal-deque", + "BlockingCollection", + "Channel" + ], + "first": "ConcurrentQueue", + "spearman": 0.9999999999999998, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 4.206896551724138, + "n_libs": 5 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "ConcurrentQueue", + "Queue+lock", + "steal-deque", + "BlockingCollection", + "Channel" + ], + "first": "ConcurrentQueue", + "spearman": 0.9999999999999998, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 0.9101123595505618, + "spread": 4.615384615384615, + "n_libs": 5 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "ConcurrentQueue", + "Queue+lock", + "steal-deque", + "BlockingCollection", + "Channel" + ], + "first": "ConcurrentQueue", + "spearman": 0.9999999999999998, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 0.9775280898876404, + "spread": 6.25, + "n_libs": 5 + } + ] + }, + "c": { + "status": "ok", + "rows": [ + { + "library": "spsc-ring", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 944.0, + "total_median_ns": 944.0, + "p50_ns": 944.0, + "mean_ns": 967.5151515151515, + "enq_median_ns": 472.0, + "write_median_ns": 472.0, + "deq_median_ns": 472.0, + "read_median_ns": 472.0, + "rel_to_fastest": 1.0 + }, + { + "library": "mutex-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1294.0, + "total_median_ns": 1294.0, + "p50_ns": 1294.0, + "mean_ns": 1374.7272727272727, + "enq_median_ns": 769.0, + "write_median_ns": 769.0, + "deq_median_ns": 523.0, + "read_median_ns": 523.0, + "rel_to_fastest": 1.3707627118644068 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1294.0, + "total_median_ns": 1294.0, + "p50_ns": 1294.0, + "mean_ns": 1355.79797979798, + "enq_median_ns": 768.0, + "write_median_ns": 768.0, + "deq_median_ns": 523.0, + "read_median_ns": 523.0, + "rel_to_fastest": 1.3707627118644068 + }, + { + "library": "lfqueue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 13664.0, + "total_median_ns": 13664.0, + "p50_ns": 13664.0, + "mean_ns": 13681.151515151516, + "enq_median_ns": 5393.0, + "write_median_ns": 5393.0, + "deq_median_ns": 8278.0, + "read_median_ns": 8278.0, + "rel_to_fastest": 14.474576271186441 + }, + { + "library": "spsc-ring", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 968.0, + "total_median_ns": 968.0, + "p50_ns": 968.0, + "mean_ns": 968.2424242424242, + "enq_median_ns": 485.0, + "write_median_ns": 485.0, + "deq_median_ns": 484.0, + "read_median_ns": 484.0, + "rel_to_fastest": 1.0 + }, + { + "library": "mutex-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1326.0, + "total_median_ns": 1326.0, + "p50_ns": 1326.0, + "mean_ns": 1362.4747474747476, + "enq_median_ns": 787.0, + "write_median_ns": 787.0, + "deq_median_ns": 536.0, + "read_median_ns": 536.0, + "rel_to_fastest": 1.3698347107438016 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1329.0, + "total_median_ns": 1329.0, + "p50_ns": 1329.0, + "mean_ns": 1374.4040404040404, + "enq_median_ns": 789.0, + "write_median_ns": 789.0, + "deq_median_ns": 537.0, + "read_median_ns": 537.0, + "rel_to_fastest": 1.3729338842975207 + }, + { + "library": "lfqueue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 14021.0, + "total_median_ns": 14021.0, + "p50_ns": 14021.0, + "mean_ns": 14067.161616161617, + "enq_median_ns": 5537.0, + "write_median_ns": 5537.0, + "deq_median_ns": 8483.0, + "read_median_ns": 8483.0, + "rel_to_fastest": 14.484504132231406 + }, + { + "library": "spsc-ring", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 969.0, + "total_median_ns": 969.0, + "p50_ns": 969.0, + "mean_ns": 980.5252525252525, + "enq_median_ns": 485.0, + "write_median_ns": 485.0, + "deq_median_ns": 484.0, + "read_median_ns": 484.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1333.0, + "total_median_ns": 1333.0, + "p50_ns": 1333.0, + "mean_ns": 1377.79797979798, + "enq_median_ns": 789.0, + "write_median_ns": 789.0, + "deq_median_ns": 537.0, + "read_median_ns": 537.0, + "rel_to_fastest": 1.3756449948400413 + }, + { + "library": "mutex-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1334.0, + "total_median_ns": 1334.0, + "p50_ns": 1334.0, + "mean_ns": 1381.8484848484848, + "enq_median_ns": 788.0, + "write_median_ns": 788.0, + "deq_median_ns": 542.0, + "read_median_ns": 542.0, + "rel_to_fastest": 1.3766769865841073 + }, + { + "library": "lfqueue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 14020.0, + "total_median_ns": 14020.0, + "p50_ns": 14020.0, + "mean_ns": 14043.020202020201, + "enq_median_ns": 5537.0, + "write_median_ns": 5537.0, + "deq_median_ns": 8483.0, + "read_median_ns": 8483.0, + "rel_to_fastest": 14.468524251805986 + }, + { + "library": "spsc-ring", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 944.0, + "total_median_ns": 944.0, + "p50_ns": 944.0, + "mean_ns": 944.060606060606, + "enq_median_ns": 472.0, + "write_median_ns": 472.0, + "deq_median_ns": 471.0, + "read_median_ns": 471.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1290.0, + "total_median_ns": 1290.0, + "p50_ns": 1290.0, + "mean_ns": 1343.050505050505, + "enq_median_ns": 765.0, + "write_median_ns": 765.0, + "deq_median_ns": 522.0, + "read_median_ns": 522.0, + "rel_to_fastest": 1.3665254237288136 + }, + { + "library": "mutex-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1326.0, + "total_median_ns": 1326.0, + "p50_ns": 1326.0, + "mean_ns": 1371.3939393939395, + "enq_median_ns": 785.0, + "write_median_ns": 785.0, + "deq_median_ns": 537.0, + "read_median_ns": 537.0, + "rel_to_fastest": 1.4046610169491525 + }, + { + "library": "lfqueue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 13996.0, + "total_median_ns": 13996.0, + "p50_ns": 13996.0, + "mean_ns": 13995.424242424242, + "enq_median_ns": 5533.0, + "write_median_ns": 5533.0, + "deq_median_ns": 8462.0, + "read_median_ns": 8462.0, + "rel_to_fastest": 14.826271186440678 + }, + { + "library": "spsc-ring", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 944.0, + "total_median_ns": 944.0, + "p50_ns": 944.0, + "mean_ns": 943.6262626262626, + "enq_median_ns": 472.0, + "write_median_ns": 472.0, + "deq_median_ns": 471.0, + "read_median_ns": 471.0, + "rel_to_fastest": 1.0 + }, + { + "library": "mutex-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1292.0, + "total_median_ns": 1292.0, + "p50_ns": 1292.0, + "mean_ns": 1337.090909090909, + "enq_median_ns": 768.0, + "write_median_ns": 768.0, + "deq_median_ns": 523.0, + "read_median_ns": 523.0, + "rel_to_fastest": 1.36864406779661 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1300.0, + "total_median_ns": 1300.0, + "p50_ns": 1300.0, + "mean_ns": 1347.989898989899, + "enq_median_ns": 768.0, + "write_median_ns": 768.0, + "deq_median_ns": 530.0, + "read_median_ns": 530.0, + "rel_to_fastest": 1.3771186440677967 + }, + { + "library": "lfqueue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 13671.0, + "total_median_ns": 13671.0, + "p50_ns": 13671.0, + "mean_ns": 13688.282828282829, + "enq_median_ns": 5393.0, + "write_median_ns": 5393.0, + "deq_median_ns": 8277.0, + "read_median_ns": 8277.0, + "rel_to_fastest": 14.481991525423728 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "spsc-ring", + "mutex-queue", + "steal-deque", + "lfqueue" + ], + "first": "spsc-ring", + "spearman": 0.9486832980505138, + "kendall": 1.0, + "flips": [ + "steal-deque vs mutex-queue" + ], + "flip_count": 1, + "time_ratio_median": 0.9742002063983488, + "spread": 14.474576271186441, + "n_libs": 4 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "spsc-ring", + "mutex-queue", + "steal-deque", + "lfqueue" + ], + "first": "spsc-ring", + "spearman": 0.7999999999999998, + "kendall": 0.6666666666666666, + "flips": [ + "steal-deque vs mutex-queue" + ], + "flip_count": 1, + "time_ratio_median": 0.9989680082559339, + "spread": 14.484504132231406, + "n_libs": 4 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "spsc-ring", + "steal-deque", + "mutex-queue", + "lfqueue" + ], + "first": "spsc-ring", + "spearman": 0.9999999999999998, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 14.468524251805986, + "n_libs": 4 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "spsc-ring", + "steal-deque", + "mutex-queue", + "lfqueue" + ], + "first": "spsc-ring", + "spearman": 0.9999999999999998, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 0.9940029985007496, + "spread": 14.826271186440678, + "n_libs": 4 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "spsc-ring", + "mutex-queue", + "steal-deque", + "lfqueue" + ], + "first": "spsc-ring", + "spearman": 0.7999999999999998, + "kendall": 0.6666666666666666, + "flips": [ + "steal-deque vs mutex-queue" + ], + "flip_count": 1, + "time_ratio_median": 0.9751069900142654, + "spread": 14.481991525423728, + "n_libs": 4 + } + ] + } + } +} \ No newline at end of file diff --git a/experiments/13-payload-size-sweep/results.md b/experiments/13-payload-size-sweep/results.md new file mode 100644 index 0000000..17671fd --- /dev/null +++ b/experiments/13-payload-size-sweep/results.md @@ -0,0 +1,91 @@ +# 13-payload-size-sweep + +Times are not comparable across languages. + +Question: which SPSC payload sizes change the ranking? + +## Recommendation + +Keep 256 B as the default small cell. Add one larger cell only when some language becomes copy-bound (handoff at least 2× and the pack collapses to about 1.3×) or the ranking inverts. Mid-pack swaps with a flat time scale are not a new size. A later inversion after the first copy-cost knee stays a research / experiment cell, not a third default type. + +Do not confuse **payload bytes per item** with **how many items** move in one repetition (`data_type_instance_count`). This folder sweeps bytes per item at n = 100. n = 1 is the wakeup experiment. n = 1000 is a throughput / amortization check, not a third size. + +**Published default matrix (two sizes)** + +- `size_256` (256 B): baseline (pointer-bound / typical small message) +- `size_4096` (4 KiB): rust: copy-bound pack collapse (time ×9.24, spread 1.19×) + +**Research / experiment only (not a default type)** + +- `size_65536` (64 KiB): rust: rank inversion (Spearman -0.357); rust: first place crossbeam-queue -> std-mpsc and time ×282.37 + +**Redundant in this run** + +- `size_1` (1 B): same first place as 256 B, no copy-bound pack collapse, no inversion. +- `size_64` (64 B): same first place as 256 B, no copy-bound pack collapse, no inversion. + +## What this means for the named types + +The published catalog names `message`, `event`, `telemetry`, `strings`, and `document` are already five lengths: 256 B, 512 B, 1 KiB, 2 KiB, and 4 KiB. Runners do not serialize those object graphs. The warehouse SPSC ranks on those names match this sweep: Python and C never change first place; JavaScript and C# only shuffle a mid-pack pair; Rust first becomes copy-bound at 4 KiB. 512 B, 1 KiB, and 2 KiB do not add a ranking question. Keep `message` (256 B) and `document` (4 KiB). Drop the three names in between from the default matrix when that change is applied. + +## Per language vs 256 B + +### python + +| Size | First | Spearman | Flips | Time × | Spread | +|------|-------|---------:|------:|-------:|-------:| +| 1 B | queue.SimpleQueue | 1.000 | 0 | 0.94 | 16.54× | +| 64 B | queue.SimpleQueue | 0.964 | 1 | 0.98 | 15.92× | +| 256 B | queue.SimpleQueue | 1.000 | 0 | 1.00 | 16.35× | +| 4 KiB | queue.SimpleQueue | 1.000 | 0 | 1.07 | 16.28× | +| 64 KiB | queue.SimpleQueue | 1.000 | 0 | 1.17 | 16.46× | + +See `python/results.md`. + +### rust + +| Size | First | Spearman | Flips | Time × | Spread | +|------|-------|---------:|------:|-------:|-------:| +| 1 B | crossbeam-queue | 0.786 | 3 | 0.99 | 2.55× | +| 64 B | crossbeam-queue | 0.964 | 1 | 0.84 | 2.40× | +| 256 B | crossbeam-queue | 1.000 | 0 | 1.00 | 2.14× | +| 4 KiB | flume | 0.750 | 4 | 9.24 | 1.19× | +| 64 KiB | std-mpsc | -0.357 | 13 | 282.37 | 1.35× | + +See `rust/results.md`. + +### javascript + +| Size | First | Spearman | Flips | Time × | Spread | +|------|-------|---------:|------:|-------:|-------:| +| 1 B | fastq | 0.829 | 2 | 2.14 | 41.17× | +| 64 B | fastq | 0.829 | 2 | 0.99 | 44.91× | +| 256 B | fastq | 1.000 | 0 | 1.00 | 32.15× | +| 4 KiB | fastq | 0.899 | 1 | 1.03 | 36.32× | +| 64 KiB | fastq | 0.771 | 3 | 1.03 | 35.48× | + +See `javascript/results.md`. + +### csharp + +| Size | First | Spearman | Flips | Time × | Spread | +|------|-------|---------:|------:|-------:|-------:| +| 1 B | ConcurrentQueue | 0.900 | 1 | 1.01 | 4.07× | +| 64 B | ConcurrentQueue | 0.900 | 1 | 1.07 | 4.03× | +| 256 B | ConcurrentQueue | 1.000 | 0 | 1.00 | 4.21× | +| 4 KiB | ConcurrentQueue | 1.000 | 0 | 0.91 | 4.62× | +| 64 KiB | ConcurrentQueue | 1.000 | 0 | 0.98 | 6.25× | + +See `csharp/results.md`. + +### c + +| Size | First | Spearman | Flips | Time × | Spread | +|------|-------|---------:|------:|-------:|-------:| +| 1 B | spsc-ring | 0.949 | 1 | 0.97 | 14.47× | +| 64 B | spsc-ring | 0.800 | 1 | 1.00 | 14.48× | +| 256 B | spsc-ring | 1.000 | 0 | 1.00 | 14.47× | +| 4 KiB | spsc-ring | 1.000 | 0 | 0.99 | 14.83× | +| 64 KiB | spsc-ring | 0.800 | 1 | 0.98 | 14.48× | + +See `c/results.md`. diff --git a/experiments/13-payload-size-sweep/run.sh b/experiments/13-payload-size-sweep/run.sh new file mode 100755 index 0000000..dc79269 --- /dev/null +++ b/experiments/13-payload-size-sweep/run.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# SPSC payload-size sweep. Uses full repetitions so rank comparisons have +# more than a handful of trials. +set -uo pipefail +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO="$(cd "$HERE/../.." && pwd)" +# shellcheck source=../../scripts/lib/config.sh +source "$REPO/scripts/lib/config.sh" + +LANGS="${*:-}" +if [[ -z "$LANGS" ]]; then + LANGS="$(bench_read_config --enabled-langs)" +fi + +export BENCHMARK_RUN_CONFIG="$HERE/run.yaml" +export BENCHMARK_SEED=42 + +while IFS='|' read -r id runner_dir runner_script; do + [[ -z "$id" ]] && continue + skip=1 + for want in $LANGS; do + [[ "$want" == "$id" ]] && skip=0 + done + [[ "$skip" -eq 1 ]] && continue + echo "=== 13-payload-size-sweep $id ===" + export LOG_DIR="$HERE/$id/logs/$id" + mkdir -p "$LOG_DIR" + bash "$REPO/$runner_dir/$runner_script" full +done < <(bench_read_config --lang-runners) + +python3 "$HERE/summarize.py" +echo "[DONE] 13-payload-size-sweep" diff --git a/experiments/13-payload-size-sweep/run.yaml b/experiments/13-payload-size-sweep/run.yaml new file mode 100644 index 0000000..23a1591 --- /dev/null +++ b/experiments/13-payload-size-sweep/run.yaml @@ -0,0 +1,20 @@ +id: 13-payload-size-sweep +description: "SPSC handoff size sweep: 1, 64, 256, 4096, 65536 bytes; 100 items" +data_model_version: 2 +types: + - type_id: size_1 + type_config: {} + - type_id: size_64 + type_config: {} + - type_id: size_256 + type_config: {} + - type_id: size_4096 + type_config: {} + - type_id: size_65536 + type_config: {} +data_type_instance_count: [100] +compression: + mode: none +execution: + mode: full + io_modes: [bytes] diff --git a/experiments/13-payload-size-sweep/rust/results.json b/experiments/13-payload-size-sweep/rust/results.json new file mode 100644 index 0000000..534db1c --- /dev/null +++ b/experiments/13-payload-size-sweep/rust/results.json @@ -0,0 +1,767 @@ +{ + "status": "ok", + "rows": [ + { + "library": "crossbeam-queue", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4107.0, + "total_median_ns": 4107.0, + "p50_ns": 4107.0, + "mean_ns": 4161.030303030303, + "enq_median_ns": 2314.0, + "write_median_ns": 2314.0, + "deq_median_ns": 1795.0, + "read_median_ns": 1795.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4425.0, + "total_median_ns": 4425.0, + "p50_ns": 4425.0, + "mean_ns": 4558.010101010101, + "enq_median_ns": 2521.0, + "write_median_ns": 2521.0, + "deq_median_ns": 1905.0, + "read_median_ns": 1905.0, + "rel_to_fastest": 1.0774287801314828 + }, + { + "library": "flume", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6472.0, + "total_median_ns": 6472.0, + "p50_ns": 6472.0, + "mean_ns": 6530.545454545455, + "enq_median_ns": 3163.0, + "write_median_ns": 3163.0, + "deq_median_ns": 3308.0, + "read_median_ns": 3308.0, + "rel_to_fastest": 1.5758461163866568 + }, + { + "library": "crossbeam-channel", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6834.0, + "total_median_ns": 6834.0, + "p50_ns": 6834.0, + "mean_ns": 6919.717171717171, + "enq_median_ns": 3373.0, + "write_median_ns": 3373.0, + "deq_median_ns": 3471.0, + "read_median_ns": 3471.0, + "rel_to_fastest": 1.6639883126369612 + }, + { + "library": "tokio-mpsc", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7745.0, + "total_median_ns": 7745.0, + "p50_ns": 7745.0, + "mean_ns": 7771.171717171717, + "enq_median_ns": 4835.0, + "write_median_ns": 4835.0, + "deq_median_ns": 2909.0, + "read_median_ns": 2909.0, + "rel_to_fastest": 1.8858047236425615 + }, + { + "library": "std-mpsc", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 9546.0, + "total_median_ns": 9546.0, + "p50_ns": 9546.0, + "mean_ns": 8903.676767676769, + "enq_median_ns": 5311.0, + "write_median_ns": 5311.0, + "deq_median_ns": 4000.0, + "read_median_ns": 4000.0, + "rel_to_fastest": 2.324324324324324 + }, + { + "library": "async-channel", + "test_data": "size_1", + "payload_bytes": 1, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 10470.0, + "total_median_ns": 10470.0, + "p50_ns": 10470.0, + "mean_ns": 11423.161616161617, + "enq_median_ns": 6293.0, + "write_median_ns": 6293.0, + "deq_median_ns": 4250.0, + "read_median_ns": 4250.0, + "rel_to_fastest": 2.5493060628195763 + }, + { + "library": "crossbeam-queue", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4542.0, + "total_median_ns": 4542.0, + "p50_ns": 4542.0, + "mean_ns": 4667.474747474747, + "enq_median_ns": 2652.0, + "write_median_ns": 2652.0, + "deq_median_ns": 1889.0, + "read_median_ns": 1889.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4601.0, + "total_median_ns": 4601.0, + "p50_ns": 4601.0, + "mean_ns": 4629.909090909091, + "enq_median_ns": 2601.0, + "write_median_ns": 2601.0, + "deq_median_ns": 2004.0, + "read_median_ns": 2004.0, + "rel_to_fastest": 1.0129898723029502 + }, + { + "library": "flume", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4887.0, + "total_median_ns": 4887.0, + "p50_ns": 4887.0, + "mean_ns": 4965.818181818182, + "enq_median_ns": 2478.0, + "write_median_ns": 2478.0, + "deq_median_ns": 2412.0, + "read_median_ns": 2412.0, + "rel_to_fastest": 1.0759577278731836 + }, + { + "library": "std-mpsc", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 4902.0, + "total_median_ns": 4902.0, + "p50_ns": 4902.0, + "mean_ns": 4932.434343434344, + "enq_median_ns": 2922.0, + "write_median_ns": 2922.0, + "deq_median_ns": 1991.0, + "read_median_ns": 1991.0, + "rel_to_fastest": 1.0792602377807134 + }, + { + "library": "crossbeam-channel", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5634.0, + "total_median_ns": 5634.0, + "p50_ns": 5634.0, + "mean_ns": 5665.818181818182, + "enq_median_ns": 2888.0, + "write_median_ns": 2888.0, + "deq_median_ns": 2759.0, + "read_median_ns": 2759.0, + "rel_to_fastest": 1.2404227212681638 + }, + { + "library": "tokio-mpsc", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6164.0, + "total_median_ns": 6164.0, + "p50_ns": 6164.0, + "mean_ns": 6192.717171717171, + "enq_median_ns": 4182.0, + "write_median_ns": 4182.0, + "deq_median_ns": 1992.0, + "read_median_ns": 1992.0, + "rel_to_fastest": 1.3571114046675474 + }, + { + "library": "async-channel", + "test_data": "size_64", + "payload_bytes": 64, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 10891.0, + "total_median_ns": 10891.0, + "p50_ns": 10891.0, + "mean_ns": 10925.20202020202, + "enq_median_ns": 6589.0, + "write_median_ns": 6589.0, + "deq_median_ns": 4284.0, + "read_median_ns": 4284.0, + "rel_to_fastest": 2.397842360193747 + }, + { + "library": "crossbeam-queue", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5350.0, + "total_median_ns": 5350.0, + "p50_ns": 5350.0, + "mean_ns": 5405.656565656565, + "enq_median_ns": 2931.0, + "write_median_ns": 2931.0, + "deq_median_ns": 2424.0, + "read_median_ns": 2424.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 5446.0, + "total_median_ns": 5446.0, + "p50_ns": 5446.0, + "mean_ns": 5504.393939393939, + "enq_median_ns": 2960.0, + "write_median_ns": 2960.0, + "deq_median_ns": 2498.0, + "read_median_ns": 2498.0, + "rel_to_fastest": 1.0179439252336449 + }, + { + "library": "std-mpsc", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6019.0, + "total_median_ns": 6019.0, + "p50_ns": 6019.0, + "mean_ns": 5936.575757575758, + "enq_median_ns": 3376.0, + "write_median_ns": 3376.0, + "deq_median_ns": 2632.0, + "read_median_ns": 2632.0, + "rel_to_fastest": 1.1250467289719626 + }, + { + "library": "flume", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6546.0, + "total_median_ns": 6546.0, + "p50_ns": 6546.0, + "mean_ns": 6656.929292929293, + "enq_median_ns": 3396.0, + "write_median_ns": 3396.0, + "deq_median_ns": 3155.0, + "read_median_ns": 3155.0, + "rel_to_fastest": 1.223551401869159 + }, + { + "library": "crossbeam-channel", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 6762.0, + "total_median_ns": 6762.0, + "p50_ns": 6762.0, + "mean_ns": 6824.181818181818, + "enq_median_ns": 3326.0, + "write_median_ns": 3326.0, + "deq_median_ns": 3436.0, + "read_median_ns": 3436.0, + "rel_to_fastest": 1.2639252336448599 + }, + { + "library": "tokio-mpsc", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 7304.0, + "total_median_ns": 7304.0, + "p50_ns": 7304.0, + "mean_ns": 7214.979797979798, + "enq_median_ns": 4663.0, + "write_median_ns": 4663.0, + "deq_median_ns": 2609.0, + "read_median_ns": 2609.0, + "rel_to_fastest": 1.365233644859813 + }, + { + "library": "async-channel", + "test_data": "size_256", + "payload_bytes": 256, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 11474.0, + "total_median_ns": 11474.0, + "p50_ns": 11474.0, + "mean_ns": 11723.29292929293, + "enq_median_ns": 6702.0, + "write_median_ns": 6702.0, + "deq_median_ns": 4776.0, + "read_median_ns": 4776.0, + "rel_to_fastest": 2.1446728971962616 + }, + { + "library": "flume", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 59130.0, + "total_median_ns": 59130.0, + "p50_ns": 59130.0, + "mean_ns": 62223.84848484849, + "enq_median_ns": 53549.0, + "write_median_ns": 53549.0, + "deq_median_ns": 5416.0, + "read_median_ns": 5416.0, + "rel_to_fastest": 1.0 + }, + { + "library": "steal-deque", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 59582.0, + "total_median_ns": 59582.0, + "p50_ns": 59582.0, + "mean_ns": 61626.09090909091, + "enq_median_ns": 54037.0, + "write_median_ns": 54037.0, + "deq_median_ns": 5518.0, + "read_median_ns": 5518.0, + "rel_to_fastest": 1.0076441738542194 + }, + { + "library": "crossbeam-queue", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 61833.0, + "total_median_ns": 61833.0, + "p50_ns": 61833.0, + "mean_ns": 64398.35353535353, + "enq_median_ns": 51876.0, + "write_median_ns": 51876.0, + "deq_median_ns": 9879.0, + "read_median_ns": 9879.0, + "rel_to_fastest": 1.045712836123795 + }, + { + "library": "std-mpsc", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62230.0, + "total_median_ns": 62230.0, + "p50_ns": 62230.0, + "mean_ns": 63522.080808080806, + "enq_median_ns": 52231.0, + "write_median_ns": 52231.0, + "deq_median_ns": 9842.0, + "read_median_ns": 9842.0, + "rel_to_fastest": 1.0524268560798242 + }, + { + "library": "crossbeam-channel", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 62478.0, + "total_median_ns": 62478.0, + "p50_ns": 62478.0, + "mean_ns": 64050.77777777778, + "enq_median_ns": 51740.0, + "write_median_ns": 51740.0, + "deq_median_ns": 10571.0, + "read_median_ns": 10571.0, + "rel_to_fastest": 1.05662100456621 + }, + { + "library": "tokio-mpsc", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 65210.0, + "total_median_ns": 65210.0, + "p50_ns": 65210.0, + "mean_ns": 68044.23232323233, + "enq_median_ns": 54640.0, + "write_median_ns": 54640.0, + "deq_median_ns": 10282.0, + "read_median_ns": 10282.0, + "rel_to_fastest": 1.1028242854726873 + }, + { + "library": "async-channel", + "test_data": "size_4096", + "payload_bytes": 4096, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 70093.0, + "total_median_ns": 70093.0, + "p50_ns": 70093.0, + "mean_ns": 73494.11111111111, + "enq_median_ns": 57328.0, + "write_median_ns": 57328.0, + "deq_median_ns": 12708.0, + "read_median_ns": 12708.0, + "rel_to_fastest": 1.1854050397429392 + }, + { + "library": "std-mpsc", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1564000.0, + "total_median_ns": 1564000.0, + "p50_ns": 1564000.0, + "mean_ns": 1732242.4141414142, + "enq_median_ns": 1438754.0, + "write_median_ns": 1438754.0, + "deq_median_ns": 121465.0, + "read_median_ns": 121465.0, + "rel_to_fastest": 1.0 + }, + { + "library": "crossbeam-channel", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1755998.0, + "total_median_ns": 1755998.0, + "p50_ns": 1755998.0, + "mean_ns": 1844903.9696969697, + "enq_median_ns": 1620795.0, + "write_median_ns": 1620795.0, + "deq_median_ns": 128929.0, + "read_median_ns": 128929.0, + "rel_to_fastest": 1.1227608695652174 + }, + { + "library": "flume", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1944333.0, + "total_median_ns": 1944333.0, + "p50_ns": 1944333.0, + "mean_ns": 2090790.3333333333, + "enq_median_ns": 1808146.0, + "write_median_ns": 1808146.0, + "deq_median_ns": 152019.0, + "read_median_ns": 152019.0, + "rel_to_fastest": 1.2431796675191815 + }, + { + "library": "async-channel", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 1963145.0, + "total_median_ns": 1963145.0, + "p50_ns": 1963145.0, + "mean_ns": 2044139.8484848484, + "enq_median_ns": 1803408.0, + "write_median_ns": 1803408.0, + "deq_median_ns": 160831.0, + "read_median_ns": 160831.0, + "rel_to_fastest": 1.255207800511509 + }, + { + "library": "tokio-mpsc", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2062398.0, + "total_median_ns": 2062398.0, + "p50_ns": 2062398.0, + "mean_ns": 2149374.8585858587, + "enq_median_ns": 1905632.0, + "write_median_ns": 1905632.0, + "deq_median_ns": 157634.0, + "read_median_ns": 157634.0, + "rel_to_fastest": 1.3186687979539642 + }, + { + "library": "steal-deque", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2096368.0, + "total_median_ns": 2096368.0, + "p50_ns": 2096368.0, + "mean_ns": 2164774.606060606, + "enq_median_ns": 1945730.0, + "write_median_ns": 1945730.0, + "deq_median_ns": 157651.0, + "read_median_ns": 157651.0, + "rel_to_fastest": 1.340388746803069 + }, + { + "library": "crossbeam-queue", + "test_data": "size_65536", + "payload_bytes": 65536, + "pattern": "bytes", + "io": "bytes", + "n": 99, + "runs": 99, + "median_handoff_ns": 2113792.0, + "total_median_ns": 2113792.0, + "p50_ns": 2113792.0, + "mean_ns": 2213570.8282828284, + "enq_median_ns": 1960205.0, + "write_median_ns": 1960205.0, + "deq_median_ns": 159693.0, + "read_median_ns": 159693.0, + "rel_to_fastest": 1.3515294117647059 + } + ], + "vs_256": [ + { + "test_data": "size_1", + "payload_bytes": 1, + "order": [ + "crossbeam-queue", + "steal-deque", + "flume", + "crossbeam-channel", + "tokio-mpsc", + "std-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.7857142857142856, + "kendall": 0.7142857142857143, + "flips": [ + "std-mpsc vs flume", + "std-mpsc vs crossbeam-channel", + "std-mpsc vs tokio-mpsc" + ], + "flip_count": 3, + "time_ratio_median": 0.9886953864955698, + "spread": 2.5493060628195763, + "n_libs": 7 + }, + { + "test_data": "size_64", + "payload_bytes": 64, + "order": [ + "crossbeam-queue", + "steal-deque", + "flume", + "std-mpsc", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.9642857142857142, + "kendall": 0.9047619047619048, + "flips": [ + "std-mpsc vs flume" + ], + "flip_count": 1, + "time_ratio_median": 0.843921139101862, + "spread": 2.397842360193747, + "n_libs": 7 + }, + { + "test_data": "size_256", + "payload_bytes": 256, + "order": [ + "crossbeam-queue", + "steal-deque", + "std-mpsc", + "flume", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "crossbeam-queue", + "spearman": 0.9999999999999999, + "kendall": 1.0, + "flips": [], + "flip_count": 0, + "time_ratio_median": 1.0, + "spread": 2.1446728971962616, + "n_libs": 7 + }, + { + "test_data": "size_4096", + "payload_bytes": 4096, + "order": [ + "flume", + "steal-deque", + "crossbeam-queue", + "std-mpsc", + "crossbeam-channel", + "tokio-mpsc", + "async-channel" + ], + "first": "flume", + "spearman": 0.7499999999999999, + "kendall": 0.6190476190476191, + "flips": [ + "crossbeam-queue vs steal-deque", + "crossbeam-queue vs flume", + "steal-deque vs flume", + "std-mpsc vs flume" + ], + "flip_count": 4, + "time_ratio_median": 9.239574090505768, + "spread": 1.1854050397429392, + "n_libs": 7 + }, + { + "test_data": "size_65536", + "payload_bytes": 65536, + "order": [ + "std-mpsc", + "crossbeam-channel", + "flume", + "async-channel", + "tokio-mpsc", + "steal-deque", + "crossbeam-queue" + ], + "first": "std-mpsc", + "spearman": -0.3571428571428571, + "kendall": -0.23809523809523808, + "flips": [ + "crossbeam-queue vs steal-deque", + "crossbeam-queue vs std-mpsc", + "crossbeam-queue vs flume", + "crossbeam-queue vs crossbeam-channel", + "crossbeam-queue vs tokio-mpsc", + "crossbeam-queue vs async-channel", + "steal-deque vs std-mpsc", + "steal-deque vs flume", + "steal-deque vs crossbeam-channel", + "steal-deque vs tokio-mpsc", + "steal-deque vs async-channel", + "flume vs crossbeam-channel", + "tokio-mpsc vs async-channel" + ], + "flip_count": 13, + "time_ratio_median": 282.3655531215772, + "spread": 1.3515294117647059, + "n_libs": 7 + } + ] +} \ No newline at end of file diff --git a/experiments/13-payload-size-sweep/rust/results.md b/experiments/13-payload-size-sweep/rust/results.md new file mode 100644 index 0000000..b932ad4 --- /dev/null +++ b/experiments/13-payload-size-sweep/rust/results.md @@ -0,0 +1,77 @@ +# rust + +Times are not comparable across languages. + +## size_1 (1 B) + +vs 256 B: Spearman 0.786, Kendall 0.714, 3 pairwise flip(s), time × 0.99. +Flips: std-mpsc vs flume; std-mpsc vs crossbeam-channel; std-mpsc vs tokio-mpsc. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| crossbeam-queue | 4107 | 1.00× | 99 | +| steal-deque | 4425 | 1.08× | 99 | +| flume | 6472 | 1.58× | 99 | +| crossbeam-channel | 6834 | 1.66× | 99 | +| tokio-mpsc | 7745 | 1.89× | 99 | +| std-mpsc | 9546 | 2.32× | 99 | +| async-channel | 10470 | 2.55× | 99 | + +## size_64 (64 B) + +vs 256 B: Spearman 0.964, Kendall 0.905, 1 pairwise flip(s), time × 0.84. +Flips: std-mpsc vs flume. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| crossbeam-queue | 4542 | 1.00× | 99 | +| steal-deque | 4601 | 1.01× | 99 | +| flume | 4887 | 1.08× | 99 | +| std-mpsc | 4902 | 1.08× | 99 | +| crossbeam-channel | 5634 | 1.24× | 99 | +| tokio-mpsc | 6164 | 1.36× | 99 | +| async-channel | 10891 | 2.40× | 99 | + +## size_256 (256 B) + +vs 256 B: Spearman 1.000, Kendall 1.000, 0 pairwise flip(s), time × 1.00. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| crossbeam-queue | 5350 | 1.00× | 99 | +| steal-deque | 5446 | 1.02× | 99 | +| std-mpsc | 6019 | 1.13× | 99 | +| flume | 6546 | 1.22× | 99 | +| crossbeam-channel | 6762 | 1.26× | 99 | +| tokio-mpsc | 7304 | 1.37× | 99 | +| async-channel | 11474 | 2.14× | 99 | + +## size_4096 (4 KiB) + +vs 256 B: Spearman 0.750, Kendall 0.619, 4 pairwise flip(s), time × 9.24. +Flips: crossbeam-queue vs steal-deque; crossbeam-queue vs flume; steal-deque vs flume; std-mpsc vs flume. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| flume | 59130 | 1.00× | 99 | +| steal-deque | 59582 | 1.01× | 99 | +| crossbeam-queue | 61833 | 1.05× | 99 | +| std-mpsc | 62230 | 1.05× | 99 | +| crossbeam-channel | 62478 | 1.06× | 99 | +| tokio-mpsc | 65210 | 1.10× | 99 | +| async-channel | 70093 | 1.19× | 99 | + +## size_65536 (64 KiB) + +vs 256 B: Spearman -0.357, Kendall -0.238, 13 pairwise flip(s), time × 282.37. +Flips: crossbeam-queue vs steal-deque; crossbeam-queue vs std-mpsc; crossbeam-queue vs flume; crossbeam-queue vs crossbeam-channel; crossbeam-queue vs tokio-mpsc; crossbeam-queue vs async-channel; steal-deque vs std-mpsc; steal-deque vs flume; steal-deque vs crossbeam-channel; steal-deque vs tokio-mpsc; steal-deque vs async-channel; flume vs crossbeam-channel; tokio-mpsc vs async-channel. + +| Library | Median handoff (ns) | vs fastest | n | +|---------|--------------------:|-----------:|--:| +| std-mpsc | 1564000 | 1.00× | 99 | +| crossbeam-channel | 1755998 | 1.12× | 99 | +| flume | 1944333 | 1.24× | 99 | +| async-channel | 1963145 | 1.26× | 99 | +| tokio-mpsc | 2062398 | 1.32× | 99 | +| steal-deque | 2096368 | 1.34× | 99 | +| crossbeam-queue | 2113792 | 1.35× | 99 | diff --git a/experiments/13-payload-size-sweep/sample.json b/experiments/13-payload-size-sweep/sample.json new file mode 100644 index 0000000..4548826 --- /dev/null +++ b/experiments/13-payload-size-sweep/sample.json @@ -0,0 +1,7 @@ +{ + "kind": "size_sweep", + "note": "Runners build an opaque byte string of each length. There is no object graph.", + "records_per_write": 100, + "sizes_bytes": [1, 64, 256, 4096, 65536], + "type_ids": ["size_1", "size_64", "size_256", "size_4096", "size_65536"] +} diff --git a/experiments/13-payload-size-sweep/summarize.py b/experiments/13-payload-size-sweep/summarize.py new file mode 100755 index 0000000..856314a --- /dev/null +++ b/experiments/13-payload-size-sweep/summarize.py @@ -0,0 +1,492 @@ +#!/usr/bin/env python3 +"""Rank stability across payload sizes for experiment 13. + +Groups by (library, type_id), not just library. Writes per-language tables +and a combined finding: which sizes change order vs 256 B. +""" + +from __future__ import annotations + +import csv +import json +import statistics +import sys +from datetime import datetime, timezone +from pathlib import Path + +HERE = Path(__file__).resolve().parent +REPO = HERE.parent.parent + +SIZE_ORDER = ["size_1", "size_64", "size_256", "size_4096", "size_65536"] +SIZE_BYTES = { + "size_1": 1, + "size_64": 64, + "size_256": 256, + "size_4096": 4096, + "size_65536": 65536, +} +BASELINE = "size_256" +# A new size is a different ranking question only if copy cost collapses +# the pack, the order inverts, or first place changes *and* time jumps. +COPY_TIME_RATIO = 2.0 +PACK_COLLAPSE_SPREAD = 1.3 +LANGS = ["python", "rust", "javascript", "csharp", "c"] + + +def latest_csv(exp_dir: Path, lang: str) -> Path | None: + root = exp_dir / lang / "logs" + files = [p for p in root.rglob("*.csv") if "errors" not in p.name] + if not files: + return None + return max(files, key=lambda p: p.stat().st_mtime) + + +def _f(row: dict, *keys: str) -> float | None: + for key in keys: + raw = row.get(key) + if raw in (None, ""): + continue + try: + return float(raw) + except (TypeError, ValueError): + continue + return None + + +def spearman(xs: list[float], ys: list[float]) -> float | None: + n = len(xs) + if n < 2: + return None + + def ranks(a: list[float]) -> list[float]: + order = sorted(range(n), key=lambda i: a[i]) + out = [0.0] * n + i = 0 + while i < n: + j = i + while j + 1 < n and a[order[j + 1]] == a[order[i]]: + j += 1 + avg = (i + j) / 2 + 1 + for k in range(i, j + 1): + out[order[k]] = avg + i = j + 1 + return out + + rx, ry = ranks(xs), ranks(ys) + mx, my = sum(rx) / n, sum(ry) / n + num = sum((a - mx) * (b - my) for a, b in zip(rx, ry)) + dx = sum((a - mx) ** 2 for a in rx) ** 0.5 + dy = sum((b - my) ** 2 for b in ry) ** 0.5 + if dx == 0 or dy == 0: + return 1.0 if dx == dy == 0 else None + return num / (dx * dy) + + +def kendall_tau(xs: list[float], ys: list[float]) -> float | None: + n = len(xs) + if n < 2: + return None + conc = disc = 0 + for i in range(n): + for j in range(i + 1, n): + dx = xs[i] - xs[j] + dy = ys[i] - ys[j] + if dx == 0 or dy == 0: + continue + if dx * dy > 0: + conc += 1 + else: + disc += 1 + tot = conc + disc + return None if tot == 0 else (conc - disc) / tot + + +def ranking(medians: dict[str, float]) -> list[str]: + return [lib for lib, _ in sorted(medians.items(), key=lambda kv: kv[1])] + + +def pairwise_flips(order_a: list[str], order_b: list[str]) -> list[tuple[str, str]]: + pos_a = {lib: i for i, lib in enumerate(order_a)} + pos_b = {lib: i for i, lib in enumerate(order_b)} + common = [lib for lib in order_a if lib in pos_b] + flips: list[tuple[str, str]] = [] + for i, a in enumerate(common): + for b in common[i + 1 :]: + if (pos_a[a] - pos_a[b]) * (pos_b[a] - pos_b[b]) < 0: + flips.append((a, b)) + return flips + + +def summarize_csv(path: Path) -> list[dict]: + rows = list(csv.DictReader(path.open(encoding="utf-8"))) + groups: dict[tuple[str, str, str], dict[str, list[float]]] = {} + for r in rows: + if r.get("RepetitionIndex") == "0": + continue + name = r.get("LibraryName") or r.get("SerializerName") or "" + pattern = r.get("Pattern") or r.get("StringOrStream") or "bytes" + type_id = r.get("TestDataName") or "" + handoff = _f(r, "TimeHandoff", "TimeSerAndDeser") + if handoff is None or not name: + continue + bucket = groups.setdefault((name, type_id, pattern), {"handoff": [], "enq": [], "deq": []}) + bucket["handoff"].append(handoff) + enq = _f(r, "TimeEnq", "TimeSer") + deq = _f(r, "TimeDeq", "TimeDeser") + if enq is not None: + bucket["enq"].append(enq) + if deq is not None: + bucket["deq"].append(deq) + + out: list[dict] = [] + for (name, type_id, mode), series in sorted(groups.items()): + vals = series["handoff"] + if not vals: + continue + med = statistics.median(vals) + row = { + "library": name, + "test_data": type_id, + "payload_bytes": SIZE_BYTES.get(type_id), + "pattern": mode, + "io": mode, + "n": len(vals), + "runs": len(vals), + "median_handoff_ns": med, + "total_median_ns": med, + "p50_ns": med, + "mean_ns": statistics.fmean(vals), + } + if series["enq"]: + row["enq_median_ns"] = statistics.median(series["enq"]) + row["write_median_ns"] = row["enq_median_ns"] + if series["deq"]: + row["deq_median_ns"] = statistics.median(series["deq"]) + row["read_median_ns"] = row["deq_median_ns"] + out.append(row) + + by_size: dict[str, list[dict]] = {} + for row in out: + by_size.setdefault(row["test_data"], []).append(row) + for chunk in by_size.values(): + chunk.sort(key=lambda r: r["median_handoff_ns"]) + best = chunk[0]["median_handoff_ns"] if chunk else 0 + for row in chunk: + row["rel_to_fastest"] = (row["median_handoff_ns"] / best) if best else 1.0 + out.sort(key=lambda r: (SIZE_BYTES.get(r["test_data"]) or 0, r["median_handoff_ns"])) + return out + + +def size_medians(rows: list[dict]) -> dict[str, dict[str, float]]: + out: dict[str, dict[str, float]] = {} + for row in rows: + out.setdefault(row["test_data"], {})[row["library"]] = row["median_handoff_ns"] + return out + + +def compare_to_baseline(medians: dict[str, dict[str, float]]) -> list[dict]: + base = medians.get(BASELINE) or {} + reports = [] + for type_id in SIZE_ORDER: + d = medians.get(type_id) or {} + common = [lib for lib in ranking(base) if lib in d] if base else ranking(d) + xs = [base[lib] for lib in common] if base else [] + ys = [d[lib] for lib in common] + order = ranking(d) + base_order = ranking({lib: base[lib] for lib in common}) if base else [] + flips = pairwise_flips(base_order, [lib for lib in order if lib in base]) if base else [] + ratios = [ + d[lib] / base[lib] + for lib in common + if base.get(lib) and base[lib] > 0 and lib in d + ] + ratios.sort() + mid = ratios[len(ratios) // 2] if ratios else None + spread = None + if d: + lo = min(d.values()) + hi = max(d.values()) + spread = (hi / lo) if lo else None + reports.append( + { + "test_data": type_id, + "payload_bytes": SIZE_BYTES[type_id], + "order": order, + "first": order[0] if order else None, + "spearman": spearman(xs, ys) if xs else None, + "kendall": kendall_tau(xs, ys) if xs else None, + "flips": [f"{a} vs {b}" for a, b in flips], + "flip_count": len(flips), + "time_ratio_median": mid, + "spread": spread, + "n_libs": len(common) if common else len(d), + } + ) + return reports + + +def regime_reasons(r: dict, base: dict, lang: str) -> list[str]: + """Reasons this size is a different ranking question than 256 B.""" + reasons: list[str] = [] + ratio = r.get("time_ratio_median") + spread = r.get("spread") + sp = r.get("spearman") + first_changed = r.get("first") and r["first"] != base.get("first") + copy_collapse = ( + ratio is not None + and ratio >= COPY_TIME_RATIO + and spread is not None + and spread <= PACK_COLLAPSE_SPREAD + ) + inversion = sp is not None and sp < 0 + first_and_copy = first_changed and ratio is not None and ratio >= COPY_TIME_RATIO + if copy_collapse: + reasons.append( + f"{lang}: copy-bound pack collapse " + f"(time ×{ratio:.2f}, spread {spread:.2f}×)" + ) + if inversion: + reasons.append(f"{lang}: rank inversion (Spearman {sp:.3f})") + if first_and_copy and not copy_collapse: + reasons.append( + f"{lang}: first place {base.get('first')} -> {r['first']} " + f"and time ×{ratio:.2f}" + ) + return reasons + + +def recommend(lang_reports: dict[str, list[dict]]) -> dict: + """Two published sizes plus an optional research size. + + Mid-pack swaps inside a tight pair (Spearman 0.8 with the same first + place and flat times) are measurement noise, not a new data type. + """ + signals: dict[str, list[str]] = {tid: [] for tid in SIZE_ORDER} + signals[BASELINE].append("baseline (pointer-bound / typical small message)") + for lang, reports in lang_reports.items(): + by_id = {r["test_data"]: r for r in reports} + base = by_id.get(BASELINE) + if not base: + continue + for r in reports: + if r["test_data"] == BASELINE: + continue + signals[r["test_data"]].extend(regime_reasons(r, base, lang)) + + default: list[str] = [BASELINE] + research: list[str] = [] + for tid in SIZE_ORDER: + if tid == BASELINE or not signals[tid]: + continue + # First copy-cost knee goes on the published matrix. A later + # inversion (64 KiB) is a third question, not a third default cell. + if not any(t != BASELINE for t in default): + default.append(tid) + else: + research.append(tid) + redundant = [tid for tid in SIZE_ORDER if tid not in default and tid not in research] + return { + "default_matrix": [ + {"test_data": tid, "payload_bytes": SIZE_BYTES[tid], "why": signals[tid]} + for tid in default + ], + "research": [ + {"test_data": tid, "payload_bytes": SIZE_BYTES[tid], "why": signals[tid]} + for tid in research + ], + "redundant": [ + {"test_data": tid, "payload_bytes": SIZE_BYTES[tid]} for tid in redundant + ], + "keep": [ + {"test_data": tid, "payload_bytes": SIZE_BYTES[tid], "why": signals[tid]} + for tid in default + ], + "drop": [ + {"test_data": tid, "payload_bytes": SIZE_BYTES[tid]} for tid in redundant + ], + "rule": ( + "Keep 256 B as the default small cell. Add one larger cell only " + "when some language becomes copy-bound (handoff at least 2× and " + "the pack collapses to about 1.3×) or the ranking inverts. " + "Mid-pack swaps with a flat time scale are not a new size. " + "A later inversion after the first copy-cost knee stays a " + "research / experiment cell, not a third default type." + ), + } + + +def fmt_bytes(n: int | None) -> str: + if n is None: + return "?" + if n >= 1024 and n % 1024 == 0: + return f"{n // 1024} KiB" + return f"{n} B" + + +def write_lang_md(path: Path, lang: str, rows: list[dict], reports: list[dict]) -> None: + lines = [ + f"# {lang}", + "", + "Times are not comparable across languages.", + "", + ] + for r in reports: + nbytes = r["payload_bytes"] + lines.append(f"## {r['test_data']} ({fmt_bytes(nbytes)})") + lines.append("") + if r["spearman"] is not None: + lines.append( + f"vs 256 B: Spearman {r['spearman']:.3f}, " + f"Kendall {r['kendall']:.3f}, " + f"{r['flip_count']} pairwise flip(s), " + f"time × {r['time_ratio_median']:.2f}." + ) + if r["flips"]: + lines.append("Flips: " + "; ".join(r["flips"]) + ".") + lines.append("") + chunk = [row for row in rows if row["test_data"] == r["test_data"]] + lines.extend( + [ + "| Library | Median handoff (ns) | vs fastest | n |", + "|---------|--------------------:|-----------:|--:|", + ] + ) + for row in chunk: + lines.append( + f"| {row['library']} | {row['median_handoff_ns']:.0f} | " + f"{row['rel_to_fastest']:.2f}× | {row['n']} |" + ) + lines.append("") + path.write_text("\n".join(lines), encoding="utf-8") + + +def write_combined_md( + path: Path, + lang_reports: dict[str, list[dict]], + recommendation: dict, + languages: dict, +) -> None: + lines = [ + "# 13-payload-size-sweep", + "", + "Times are not comparable across languages.", + "", + "Question: which SPSC payload sizes change the ranking?", + "", + "## Recommendation", + "", + recommendation["rule"], + "", + "Do not confuse **payload bytes per item** with **how many items** " + "move in one repetition (`data_type_instance_count`). This folder " + "sweeps bytes per item at n = 100. n = 1 is the wakeup experiment. " + "n = 1000 is a throughput / amortization check, not a third size.", + "", + ] + if recommendation.get("default_matrix"): + lines.append("**Published default matrix (two sizes)**") + lines.append("") + for item in recommendation["default_matrix"]: + why = "; ".join(item["why"]) if item["why"] else "baseline" + lines.append(f"- `{item['test_data']}` ({fmt_bytes(item['payload_bytes'])}): {why}") + lines.append("") + if recommendation.get("research"): + lines.append("**Research / experiment only (not a default type)**") + lines.append("") + for item in recommendation["research"]: + why = "; ".join(item["why"]) if item["why"] else "" + lines.append(f"- `{item['test_data']}` ({fmt_bytes(item['payload_bytes'])}): {why}") + lines.append("") + if recommendation.get("redundant"): + lines.append("**Redundant in this run**") + lines.append("") + for item in recommendation["redundant"]: + lines.append( + f"- `{item['test_data']}` ({fmt_bytes(item['payload_bytes'])}): " + "same first place as 256 B, no copy-bound pack collapse, no inversion." + ) + lines.append("") + lines.extend( + [ + "## What this means for the named types", + "", + "The published catalog names `message`, `event`, `telemetry`, " + "`strings`, and `document` are already five lengths: 256 B, 512 B, " + "1 KiB, 2 KiB, and 4 KiB. Runners do not serialize those object " + "graphs. The warehouse SPSC ranks on those names match this sweep: " + "Python and C never change first place; JavaScript and C# only " + "shuffle a mid-pack pair; Rust first becomes copy-bound at 4 KiB. " + "512 B, 1 KiB, and 2 KiB do not add a ranking question. Keep " + "`message` (256 B) and `document` (4 KiB). Drop the three names " + "in between from the default matrix when that change is applied.", + "", + "## Per language vs 256 B", + "", + ] + ) + for lang, reports in lang_reports.items(): + lines.append(f"### {lang}") + lines.append("") + lines.append( + "| Size | First | Spearman | Flips | Time × | Spread |" + ) + lines.append("|------|-------|---------:|------:|-------:|-------:|") + for r in reports: + sp = "—" if r["spearman"] is None else f"{r['spearman']:.3f}" + tr = "—" if r["time_ratio_median"] is None else f"{r['time_ratio_median']:.2f}" + spr = "—" if r["spread"] is None else f"{r['spread']:.2f}×" + lines.append( + f"| {fmt_bytes(r['payload_bytes'])} | {r['first'] or '—'} | {sp} | " + f"{r['flip_count']} | {tr} | {spr} |" + ) + lines.append("") + lines.append(f"See `{lang}/results.md`.") + lines.append("") + path.write_text("\n".join(lines), encoding="utf-8") + _ = languages + + +def main() -> int: + exp = HERE + if len(sys.argv) > 1: + exp = Path(sys.argv[1]).resolve() + languages: dict = {} + lang_reports: dict[str, list[dict]] = {} + for lang in LANGS: + csv_path = latest_csv(exp, lang) + if not csv_path: + continue + rows = summarize_csv(csv_path) + reports = compare_to_baseline(size_medians(rows)) + languages[lang] = {"status": "ok", "rows": rows, "vs_256": reports} + lang_reports[lang] = reports + lang_dir = exp / lang + lang_dir.mkdir(exist_ok=True) + (lang_dir / "results.json").write_text( + json.dumps({"status": "ok", "rows": rows, "vs_256": reports}, indent=2), + encoding="utf-8", + ) + write_lang_md(lang_dir / "results.md", lang, rows, reports) + recommendation = recommend(lang_reports) + payload = { + "generated_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), + "question": "Which SPSC payload sizes change the ranking?", + "sizes_bytes": [SIZE_BYTES[t] for t in SIZE_ORDER], + "baseline_bytes": SIZE_BYTES[BASELINE], + "recommendation": recommendation, + "languages": languages, + } + (exp / "results.json").write_text(json.dumps(payload, indent=2), encoding="utf-8") + write_combined_md(exp / "results.md", lang_reports, recommendation, languages) + print(f"wrote {exp / 'results.json'} langs={list(languages)}") + if recommendation.get("default_matrix"): + kept = ", ".join(f"{i['payload_bytes']} B" for i in recommendation["default_matrix"]) + print(f"default matrix: {kept}") + if recommendation.get("research"): + extra = ", ".join(f"{i['payload_bytes']} B" for i in recommendation["research"]) + print(f"research only: {extra}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/experiments/PLAN.md b/experiments/PLAN.md index 312a9a9..d7f9421 100644 --- a/experiments/PLAN.md +++ b/experiments/PLAN.md @@ -17,6 +17,33 @@ by relative handoff time vs the fastest on that sample. Do not crown a winner. | 10 | [10-process-ipc](10-process-ipc/) | Ready | Category P vs in-process | | 11 | [11-shared-memory](11-shared-memory/) | Ready | Category S ring | | 12 | [12-durable-local](12-durable-local/) | Ready | Category D sqlite | +| 13 | [13-payload-size-sweep](13-payload-size-sweep/) | Ready | Which payload sizes change SPSC ranking | T1=01, T2=02, T3=03, T4=04, T5=05, T6=06, A2=07, A3=08, A4=09. P/S/D have Python runners only. Do not plot P/S/D next to T. +Experiment 13 is a methodology question about the default matrix, not a new communication category. + +## After Experiment 13 + +SPSC ranking is a **size** question, not a data-type question. Runners already +build opaque byte strings. The five published names are five lengths between +256 B and 4 KiB. + +Sweep (1 B, 64 B, 256 B, 4 KiB, 64 KiB; n = 100; 99 trials after warmup): + +- Python, C, C#, JavaScript: first place never changes. Mid-pack swaps are + tight pairs (often a nanosecond). Times stay flat even at 64 KiB + (pointer / handle passing). +- Rust: 1 B and 64 B match 256 B. At 4 KiB the pack collapses (about 9× + slower, 1.19× spread) — copy cost erases the small-payload ranking. At + 64 KiB the order inverts (Spearman −0.36, about 280× slower). + +**Default matrix: two sizes, 256 B (`message`) and 4 KiB (`document`).** +Drop `event` / `telemetry` / `strings`. Keep 64 KiB as this experiment, not +a third published type. Do not use item count 1 / 100 / 10000 as a substitute +for payload bytes. + +The default run config is not changed in this PR. Apply the collapse in a +follow-up that re-runs the published suite. + +Combined page: `experiments/13-payload-size-sweep/results.md`. diff --git a/experiments/README.md b/experiments/README.md index 1e88583..0906f5a 100644 --- a/experiments/README.md +++ b/experiments/README.md @@ -19,6 +19,7 @@ Each language run is a subfolder. Combined numbers live in `results.json`. - Experiment 10: [`10-process-ipc/`](10-process-ipc/) — category P - Experiment 11: [`11-shared-memory/`](11-shared-memory/) — category S - Experiment 12: [`12-durable-local/`](12-durable-local/) — category D +- Experiment 13: [`13-payload-size-sweep/`](13-payload-size-sweep/) — which payload sizes change ranking ```bash ./experiments/01-spsc-handoff/run.sh python diff --git a/schemas/data_catalog_v2.yaml b/schemas/data_catalog_v2.yaml index d91f997..790e85e 100644 --- a/schemas/data_catalog_v2.yaml +++ b/schemas/data_catalog_v2.yaml @@ -81,3 +81,36 @@ types: min: 3 max: 12 include_payload_bytes: 0 + + # Explicit size labels for the payload-size sweep (experiment 13). + # Runners still build an opaque byte string; these ids exist so results + # can name the size instead of overloading message/document/event. + size_1: + description: "1-byte payload (pointer / handle bound)" + category: opaque_bytes + default_type_config: + payload_bytes: 1 + + size_64: + description: "64-byte payload (one cache line)" + category: opaque_bytes + default_type_config: + payload_bytes: 64 + + size_256: + description: "256-byte payload (same size as message)" + category: opaque_bytes + default_type_config: + payload_bytes: 256 + + size_4096: + description: "4 KiB payload (same size as document)" + category: opaque_bytes + default_type_config: + payload_bytes: 4096 + + size_65536: + description: "64 KiB payload (larger than typical L1)" + category: opaque_bytes + default_type_config: + payload_bytes: 65536 From 9f33801fb3412d72eec4e660b7ef52de8d3064dc Mon Sep 17 00:00:00 2001 From: leo-gan Date: Tue, 1 Sep 2026 15:24:13 -0700 Subject: [PATCH 2/5] docs(experiments): link Experiment 13 PR in PLAN --- experiments/PLAN.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experiments/PLAN.md b/experiments/PLAN.md index d7f9421..e1b8d19 100644 --- a/experiments/PLAN.md +++ b/experiments/PLAN.md @@ -47,3 +47,4 @@ The default run config is not changed in this PR. Apply the collapse in a follow-up that re-runs the published suite. Combined page: `experiments/13-payload-size-sweep/results.md`. +PR: https://github.com/leo-gan/queue-benchmark/pull/32 From d68bdfd3d12070d7f92c52bd352d48e6d1898940 Mon Sep 17 00:00:00 2001 From: leo-gan Date: Tue, 1 Sep 2026 15:28:15 -0700 Subject: [PATCH 3/5] docs: require full-sentence explanations, not clipped systems jargon Voice in STYLE.md now covers replies to the user. Experiment findings must follow that section instead of restating a shorter rule. --- .grok/skills/implement-experiment/SKILL.md | 2 +- .grok/skills/improve-docs/references/STYLE.md | 4 +++- experiments/PLAN.md | 15 +++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.grok/skills/implement-experiment/SKILL.md b/.grok/skills/implement-experiment/SKILL.md index 1444675..8e86e13 100644 --- a/.grok/skills/implement-experiment/SKILL.md +++ b/.grok/skills/implement-experiment/SKILL.md @@ -42,7 +42,7 @@ export PATH="${HOME}/.local/go/bin:${HOME}/.cargo/bin:${HOME}/.dotnet:${HOME}/.l 4. **Shared sample** at the experiment root (`sample.json`). Language folders hold **results** only (`results.md`, `results.json`). **Do not commit experiment logs** (CSVs under `/logs/`). Those stay on the machine that ran the timing. Saved results are enough. 5. **Do not compare times across languages.** Different runtimes. Directional only. Do not invent a size contest — payload bytes are the **data type**, not a library score. 6. **Do not crown a single winner.** Use `top_group` (similar / close / slower via Cliff’s delta vs the fastest library in the comparison set). Not “top 5%.” -7. **Textbook language** in `experiment.yaml` (`story.example`, `story.tradeoff`, `story.why`), `README.md`, `results.md`, the Dashboard, and the PLAN update. Write for a high-school student: complete sentences, no slang, no telegraphic fragments, no unexplained jargon. The Dashboard copies `story` from `experiment.yaml`. +7. **Textbook language** — follow `.grok/skills/improve-docs/references/STYLE.md` § Voice. That includes the finding you tell the user, not only `experiment.yaml` (`story.example`, `story.tradeoff`, `story.why`), `README.md`, `results.md`, the Dashboard, and the PLAN update. The Dashboard copies `story` from `experiment.yaml`. 8. **Do not overwrite** published site tables (`docs//results.md`) or dashboard `*_latest.json.gz` unless the user asked to publish suite numbers. 9. After the run, **update `experiments/PLAN.md`**: mark the item done, add an **After Experiment *n*** block, change later questions only if the finding requires it. Do not rewrite old findings. diff --git a/.grok/skills/improve-docs/references/STYLE.md b/.grok/skills/improve-docs/references/STYLE.md index 9e09833..0fc7c4b 100644 --- a/.grok/skills/improve-docs/references/STYLE.md +++ b/.grok/skills/improve-docs/references/STYLE.md @@ -38,15 +38,17 @@ Do not measure or display payload **size** as a library result. Size is the data ### Voice - **Textbook quality for a high-school student.** Complete sentences. One idea, then the reason. Define a term the first time it is not everyday English. +- This Voice section applies to **replies to the user** as well as published copy. A chat explanation is reader-facing. - No slang (“at 3 a.m.”, “chatty ping”, “get user”). - No telegraphic fragments (“Keep YAML on disk. Convert once.”). Write the sentence out. - No unexplained jargon (stream, socket, pickle, gzip) unless the next sentence says what it is. +- **No clipped systems metaphors.** Do not write “pass a handle”, “pointer-bound”, “copy-bound”, “pack collapse”, “size barely moves them”, or “the knee” as if those were ordinary English. First say what the computer does, then what the clocks did. Example: the queue either copies every byte of the message, or it stores a short reference to a message that is already in memory. A larger message then either takes longer (because every byte is copied) or it does not (because only the reference is moved). - Direct, calm. Not marketing hype (“blazing”, “crush”). - “We measure …” not “We revolutionize …”. - **No slogan stacks** under the title (“Same A. Same B. Same C.”). - **No lede hedges** that argue with imaginary critics (“not marketing microbenchmarks”). -This rule applies to **every** reader-facing surface: Dashboard story cards (Why / Example / Trade-off), experiment YAML, `docs/experiments/`, Learn pages, README. The Dashboard reads Example and Trade-off from `experiments/*/experiment.yaml` via `sync-experiments.py`. +This rule applies to **every** reader-facing surface: replies to the user, Dashboard story cards (Why / Example / Trade-off), experiment YAML, `results.md`, `experiments/PLAN.md`, `docs/experiments/`, Learn pages, README. The Dashboard reads Example and Trade-off from `experiments/*/experiment.yaml` via `sync-experiments.py`. ### README-specific (authoritative) diff --git a/experiments/PLAN.md b/experiments/PLAN.md index e1b8d19..020947d 100644 --- a/experiments/PLAN.md +++ b/experiments/PLAN.md @@ -31,12 +31,15 @@ build opaque byte strings. The five published names are five lengths between Sweep (1 B, 64 B, 256 B, 4 KiB, 64 KiB; n = 100; 99 trials after warmup): -- Python, C, C#, JavaScript: first place never changes. Mid-pack swaps are - tight pairs (often a nanosecond). Times stay flat even at 64 KiB - (pointer / handle passing). -- Rust: 1 B and 64 B match 256 B. At 4 KiB the pack collapses (about 9× - slower, 1.19× spread) — copy cost erases the small-payload ranking. At - 64 KiB the order inverts (Spearman −0.36, about 280× slower). +- Python, C, C#, and JavaScript: the fastest queue stays the same at every + size. Nearby libraries sometimes swap places by a nanosecond. Making the + message larger does not make the handoff much slower, because these + queues store a short reference to the bytes already in memory instead of + copying every byte. +- Rust: 1 B and 64 B match 256 B. At 4 KiB the queues copy the bytes, so + every library takes about nine times longer and they finish within about + 20 percent of each other. At 64 KiB the copy is so expensive that the + small-message order reverses (Spearman −0.36, about 280 times slower). **Default matrix: two sizes, 256 B (`message`) and 4 KiB (`document`).** Drop `event` / `telemetry` / `strings`. Keep 64 KiB as this experiment, not From 8ce449234cf8421b180d5d01ef725e6c7668f75d Mon Sep 17 00:00:00 2001 From: leo-gan Date: Tue, 1 Sep 2026 15:39:06 -0700 Subject: [PATCH 4/5] refactor: publish two payload sizes, 256 B and 4 KiB Experiment 13 showed that only these lengths change SPSC ranking. The default matrix and smoke path now use size_256 and size_4096. The dashboard filter is payload size. Older experiment folders still use message and document for the same lengths. --- .grok/skills/implement-experiment/SKILL.md | 4 +- .grok/skills/improve-docs/SKILL.md | 2 +- .grok/skills/improve-docs/references/STYLE.md | 11 ++-- .grok/skills/prepare-pr/SKILL.md | 1 + .../scripts/detect-changed-langs.sh | 2 +- README.md | 3 +- analysis/README.md | 2 +- analysis/src/benchmark_analysis/reports.py | 37 +++++++++---- analysis/tests/test_run_config_v2.py | 10 ++-- c-sharp/scripts/run-benchmarks.sh | 2 +- c/scripts/run-benchmarks.sh | 2 +- config/benchmark_config.yaml | 28 +++------- config/library/README.md | 9 +-- config/library/default.yaml | 12 +--- config/library/smoke.yaml | 4 +- dashboard/index.html | 18 +++--- dashboard/main.js | 55 ++++++++++++++----- docs/analysis/BENCHMARK_DESIGN.md | 10 ++-- docs/analysis/METRICS.md | 4 +- docs/analysis/modes.md | 4 +- docs/analysis/test_data_configuration.md | 25 ++++----- docs/internal/DESIGN.md | 8 +-- experiments/PLAN.md | 4 +- javascript/scripts/run-benchmarks.sh | 2 +- python/scripts/run-benchmarks.sh | 2 +- python/src/benchmark/data.py | 5 ++ python/tests/test_runner.py | 4 +- rust/scripts/run-benchmarks.sh | 2 +- 28 files changed, 152 insertions(+), 120 deletions(-) diff --git a/.grok/skills/implement-experiment/SKILL.md b/.grok/skills/implement-experiment/SKILL.md index 8e86e13..3f13f3f 100644 --- a/.grok/skills/implement-experiment/SKILL.md +++ b/.grok/skills/implement-experiment/SKILL.md @@ -40,7 +40,7 @@ export PATH="${HOME}/.local/go/bin:${HOME}/.cargo/bin:${HOME}/.dotnet:${HOME}/.l 2. **One question per folder.** Number it `NN-short-kebab` (next free `NN` after existing dirs). 3. **Edit `experiment.yaml` only** for sample, languages, libraries, run mode, grouping cut-offs. `run.yaml` is generated. Do not keep a second library list. 4. **Shared sample** at the experiment root (`sample.json`). Language folders hold **results** only (`results.md`, `results.json`). **Do not commit experiment logs** (CSVs under `/logs/`). Those stay on the machine that ran the timing. Saved results are enough. -5. **Do not compare times across languages.** Different runtimes. Directional only. Do not invent a size contest — payload bytes are the **data type**, not a library score. +5. **Do not compare times across languages.** Different runtimes. Directional only. Do not invent a size contest — payload size is the sample, not a library score. 6. **Do not crown a single winner.** Use `top_group` (similar / close / slower via Cliff’s delta vs the fastest library in the comparison set). Not “top 5%.” 7. **Textbook language** — follow `.grok/skills/improve-docs/references/STYLE.md` § Voice. That includes the finding you tell the user, not only `experiment.yaml` (`story.example`, `story.tradeoff`, `story.why`), `README.md`, `results.md`, the Dashboard, and the PLAN update. The Dashboard copies `story` from `experiment.yaml`. 8. **Do not overwrite** published site tables (`docs//results.md`) or dashboard `*_latest.json.gz` unless the user asked to publish suite numbers. @@ -97,7 +97,7 @@ Copy Experiment 1’s file and change: |-----|-------------| | `id` | Folder name (`NN-short-kebab`) | | `title` / `question` | From the PLAN section (ordinary words) | -| `sample.kind` | `message` \| `document` \| `telemetry` \| `strings` \| `event` | +| `sample.kind` | `size_256` \| `size_4096` \| `message` \| `document` | | `sample.records_per_write` | `1` or `[1, 100]` | | `sample.settings` | Only extra knobs (e.g. `points: 128`). `{}` = catalog defaults | | `sample.seed` | `42` unless the PLAN says otherwise | diff --git a/.grok/skills/improve-docs/SKILL.md b/.grok/skills/improve-docs/SKILL.md index 12de277..9f265b2 100644 --- a/.grok/skills/improve-docs/SKILL.md +++ b/.grok/skills/improve-docs/SKILL.md @@ -87,7 +87,7 @@ Cut scope creep, ensure dismissible UI is not permanent noise, prefer small diff - Edit sources under `dashboard/` then **`npm run build`** in `dashboard/` so `docs/dashboard/` updates. - **README:** follow `README_EDITING.md` — short lede, compact audience table, section order Who → languages → Try it → Quick start; no slogan/meta CTA prose; no unsolicited role expansion. - MkDocs storefront (`docs/index.md`) only if asked or if it clearly contradicts a user-approved README fact. -- Follow `STYLE.md` (simple, no new frameworks). **Terminology: always “data type”, never “fixture”** — in user copy, comments, identifiers, and JSON keys. +- Follow `STYLE.md` (simple, no new frameworks). **Terminology:** published filter is **payload size**; never say “fixture”. Catalog ids stay type_id values. ### 2.5 Critique the implementation diff --git a/.grok/skills/improve-docs/references/STYLE.md b/.grok/skills/improve-docs/references/STYLE.md index 0fc7c4b..4ee3f18 100644 --- a/.grok/skills/improve-docs/references/STYLE.md +++ b/.grok/skills/improve-docs/references/STYLE.md @@ -6,11 +6,12 @@ Keep it simple. Prefer delete and clarify over decorate. | Say | Never say | |-----|-----------| -| **data type** (`message`, `document`, `telemetry`, `strings`, `event`) | fixture, fixtures, fixtureKey, `dataset.fixtures` | +| **payload size** (256 B, 4 KiB) for the published filter | fixture; five leftover type names as if they were different shapes | +| **data type** only as the catalog id (`size_256`, `size_4096`) | fixture, fixtures, fixtureKey, `dataset.fixtures` | -This is the catalog payload shape. Use **data type** in README, Dashboard copy, skills, comments, function names, and new JSON keys. Do not keep `fixture*` as an internal alias. Old `configs.json` may still contain `fixtures`; read it as a fallback, write `data_types`. +The published axis is how many bytes each queued item is. Experiment 13 showed that 256 B and 4 KiB tell different stories; 512 B / 1 KiB / 2 KiB do not. Use **payload size** in README, Dashboard copy, and findings. Catalog ids stay `type_id` values (`size_256`, `size_4096`). Older folders may still say `message` / `document` (same lengths). Do not keep `fixture*` as an internal alias. Old `configs.json` may still contain `fixtures`; read it as a fallback, write `data_types`. -Do not measure or display payload **size** as a library result. Size is the data type, not a score. +Do not rank a library on payload size. Every queue in a cell moves the same bytes. Size is the sample, not a score. --- @@ -28,8 +29,8 @@ Do not measure or display payload **size** as a library result. Size is the data ## Content style - **One idea per paragraph.** Prefer tables for role/path matrices **on the site / Dashboard**, not by fattening the root README. -- **User terms:** data type, mode (bytes/stream), ops/s, latency, Pareto, baseline. -- **Never say “fixture”.** The catalog entry is a **data type** (`message`, `document`, …). Say it in docs, Dashboard copy, skills, comments, identifiers, and JSON keys. Do not keep `fixture*` as an internal alias “until later.” +- **User terms:** payload size (256 B, 4 KiB), mode (bytes/stream), ops/s, latency, Pareto, baseline. +- **Never say “fixture”.** The published sample is a **payload size**. The catalog id is a **data type** (`size_256`, `size_4096`). Say that in docs, Dashboard copy, skills, comments, identifiers, and JSON keys. Do not keep `fixture*` as an internal alias “until later.” - **Avoid in user copy:** fixture, median size (we do not measure payload size as a result), harness (prefer benchmark runner), unexplained IQR/P95. - **Honesty line** when ranks appear: within one language; cross-lang directional — prefer **one** place (e.g. Statistics / Method), not a second essay block on README. - **Links:** prefer site paths that match MkDocs nav labels (Dashboard, Learn, Method). Avoid “storefront” / “CTA” wording in user-facing labels. diff --git a/.grok/skills/prepare-pr/SKILL.md b/.grok/skills/prepare-pr/SKILL.md index d92c0f4..4121610 100644 --- a/.grok/skills/prepare-pr/SKILL.md +++ b/.grok/skills/prepare-pr/SKILL.md @@ -137,6 +137,7 @@ export PREPARE_PR_LANGS="${PREPARE_PR_LANGS:-$CHANGED_LANGS}" | `schemas/**` **except** prose (see below) | → **all** enabled languages | | `scripts/run-all-benchmarks.sh`, `scripts/lib/**`, `scripts/read-config.py`, `scripts/resolve_run_config.py` | → **all** | | `config/benchmark_config.yaml` | → **all** | +| `config/library/*` (default / smoke run matrix) | → **all** | | **Always ignored (never select langs, never force-all)** | | | `docs/**`, `dashboard/public/data/**`, `logs/**`, `reports/**`, `site/**`, `.grok/**` | meta / published artifacts | | `**/*.md`, `**/*.mdx`, `**/README*`, `LICENSE*` **anywhere** (including under `schemas/`, `scripts/`, or a language tree) | prose-only; e.g. terminology edits in `schemas/v2/README.md` must **not** re-bench the world | diff --git a/.grok/skills/prepare-pr/scripts/detect-changed-langs.sh b/.grok/skills/prepare-pr/scripts/detect-changed-langs.sh index cd28b76..ee08e8d 100755 --- a/.grok/skills/prepare-pr/scripts/detect-changed-langs.sh +++ b/.grok/skills/prepare-pr/scripts/detect-changed-langs.sh @@ -98,7 +98,7 @@ is_shared_force_all() { scripts/run-all-benchmarks.sh|scripts/lib/*|scripts/read-config.py|scripts/resolve_run_config.py|scripts/emit-cells-tsv.py) return 0 ;; - config/benchmark_config.yaml) + config/benchmark_config.yaml|config/library/*) return 0 ;; esac diff --git a/README.md b/README.md index ac67747..51dc79a 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,8 @@ commit before `publish-docs` deploys the site. ## Test data -Shared **payload types**: `message`, `document`, `telemetry`, `strings`, and `event`. +Shared **payload sizes**: 256 B (`size_256`) and 4 KiB (`size_4096`). Every +runner builds an opaque byte string of that length. Catalog and defaults: `schemas/data_catalog_v2.yaml`. Run matrices: `config/library/`. diff --git a/analysis/README.md b/analysis/README.md index 7a36fb8..8be9a60 100644 --- a/analysis/README.md +++ b/analysis/README.md @@ -14,7 +14,7 @@ uv pip install -e . Each run writes a timestamped `YYYY-MM-DD-HHMMSS.csv` (never overwritten). Analysis picks the **latest** per language by default. -Suite type ids: `message`, `document`, `telemetry`, `strings`, `event`. +Suite type ids: `size_256` (256 B), `size_4096` (4 KiB). ```bash analyze-benchmarks diff --git a/analysis/src/benchmark_analysis/reports.py b/analysis/src/benchmark_analysis/reports.py index 5b8340c..7b97e9f 100644 --- a/analysis/src/benchmark_analysis/reports.py +++ b/analysis/src/benchmark_analysis/reports.py @@ -56,13 +56,27 @@ def _stat_get(entry: Any, field_id: str) -> Any: _FIXTURE_KEY_RE = re.compile(r"^(.*?)(?:@n=(\d+))+$", re.IGNORECASE) +_PAYLOAD_SIZE_LABELS = { + "size_1": "1 B", + "size_64": "64 B", + "size_256": "256 B", + "size_4096": "4 KiB", + "size_65536": "64 KiB", + "message": "256 B", + "document": "4 KiB", + "event": "512 B", + "telemetry": "1 KiB", + "strings": "2 KiB", +} + + def _format_data_type_display(label: str) -> str: - """Decode cryptic ``message@n=100`` keys for titles and table headers. + """Decode ``size_256@n=100`` keys for titles and table headers. Examples: - ``message@n=1`` → ``Message · 1 instance`` - ``message@n=100`` → ``Message · 100 instances`` - ``document`` → ``Document`` + ``size_256@n=1`` → ``256 B · 1 item`` + ``size_4096@n=100`` → ``4 KiB · 100 items`` + ``message`` → ``256 B`` """ s = str(label or "").strip() if not s: @@ -77,15 +91,16 @@ def _format_data_type_display(label: str) -> str: else: base, n = s, None - # Suite type_ids are lowercase words; older labels may already be Title/Pascal. - if base and base == base.lower() and re.fullmatch(r"[a-z][a-z0-9_]*", base): - pretty = base.replace("_", " ").title() - else: - pretty = base + pretty = _PAYLOAD_SIZE_LABELS.get(base) + if pretty is None: + if base and base == base.lower() and re.fullmatch(r"[a-z][a-z0-9_]*", base): + pretty = base.replace("_", " ").title() + else: + pretty = base if n is None: return pretty - unit = "instance" if n == 1 else "instances" + unit = "item" if n == 1 else "items" return f"{pretty} · {n} {unit}" @@ -1393,7 +1408,7 @@ def generate_language_results_pages( "", "| Term | Meaning |", "|------|---------|", - "| **data type** | Sample shape: `message`, `document`, `telemetry`, `strings`, or `event` " + "| **payload size** | How many bytes each item is: `size_256` (256 B) or `size_4096` (4 KiB) " "(CSV `TestDataName`) |", "| **bytes mode** | In-memory buffer API (encode to bytes / decode from a buffer). " "On C# this is often the **string** path — see [Modes](../analysis/modes.md). |", diff --git a/analysis/tests/test_run_config_v2.py b/analysis/tests/test_run_config_v2.py index cc06f12..91f0ed9 100644 --- a/analysis/tests/test_run_config_v2.py +++ b/analysis/tests/test_run_config_v2.py @@ -81,17 +81,19 @@ def test_type_config_hash_stable(): def test_smoke_expand_cell_count(): resolved = resolve_run_config(_LIBRARY / "smoke.yaml", catalog_path=_CATALOG, seed=42) - assert resolved["cell_count"] == 1 # message × [1] + assert resolved["cell_count"] == 1 # size_256 × [1] assert resolved["seed"] == 42 assert resolved["run_config"]["content_sha256"] ids = {(c["type_id"], c["data_type_instance_count"]) for c in resolved["cells"]} - assert ids == {("message", 1)} + assert ids == {("size_256", 1)} def test_default_expand_cell_count(): resolved = resolve_run_config(_LIBRARY / "default.yaml", catalog_path=_CATALOG) - # 5 types × 2 counts - assert resolved["cell_count"] == 10 + # 2 sizes × 2 counts + assert resolved["cell_count"] == 4 + ids = {c["type_id"] for c in resolved["cells"]} + assert ids == {"size_256", "size_4096"} counts = {c["data_type_instance_count"] for c in resolved["cells"]} assert counts == {100, 1000} diff --git a/c-sharp/scripts/run-benchmarks.sh b/c-sharp/scripts/run-benchmarks.sh index 2c98c24..520147b 100755 --- a/c-sharp/scripts/run-benchmarks.sh +++ b/c-sharp/scripts/run-benchmarks.sh @@ -25,7 +25,7 @@ else REPS="$(bench_mode_reps "$MODE")" if [[ "$MODE" == "smoke" ]]; then FILTER_SER="${FILTER_SER:-Queue+lock}" - FILTER_DATA="${FILTER_DATA:-message}" + FILTER_DATA="${FILTER_DATA:-size_256}" fi fi diff --git a/c/scripts/run-benchmarks.sh b/c/scripts/run-benchmarks.sh index 3488ab4..7c54746 100755 --- a/c/scripts/run-benchmarks.sh +++ b/c/scripts/run-benchmarks.sh @@ -25,7 +25,7 @@ else REPS="$(bench_mode_reps "$MODE")" if [[ "$MODE" == "smoke" ]]; then FILTER_SER="${FILTER_SER:-mutex-queue}" - FILTER_DATA="${FILTER_DATA:-message}" + FILTER_DATA="${FILTER_DATA:-size_256}" fi fi diff --git a/config/benchmark_config.yaml b/config/benchmark_config.yaml index ddd98dc..a81603f 100644 --- a/config/benchmark_config.yaml +++ b/config/benchmark_config.yaml @@ -53,30 +53,18 @@ data_model_v2: schemas_root: "schemas/v2" generate_script: "scripts/schemas/generate-all.sh" -# Payload shapes. Catalog is normative; names are type_id values. -# For queues these are payload sizes / shapes, not object graphs. +# Payload sizes. Catalog is normative; names are type_id values. +# For queues these are lengths of an opaque byte string, not object graphs. test_data: catalog_file: "schemas/data_catalog_v2.yaml" types: - - name: message - category: flat_mixed - description: "Small message payload (~256 B)" + - name: size_256 + category: opaque_bytes + description: "256-byte payload (small message)" supports_circular: false - - name: document - category: nested - description: "Larger document payload (~4 KiB)" - supports_circular: false - - name: telemetry - category: numeric_bulk - description: "Numeric bulk payload (~1 KiB)" - supports_circular: false - - name: strings - category: text_bulk - description: "Text bulk payload (~2 KiB)" - supports_circular: false - - name: event - category: envelope - description: "Event envelope payload (~512 B)" + - name: size_4096 + category: opaque_bytes + description: "4 KiB payload (copy cost starts to matter)" supports_circular: false # Pattern axis (CSV StringOrStream). Logged names are serializer ABI leftovers: diff --git a/config/library/README.md b/config/library/README.md index 82ab457..6a22369 100644 --- a/config/library/README.md +++ b/config/library/README.md @@ -6,15 +6,16 @@ Named **run configs** select the measurement matrix: - `data_type_instance_count` (axis C): items moved per repetition - `execution.io_modes`: `bytes` = **SPSC**, `stream` = **MPMC** (legacy name; not I/O) -Type ids: `message` · `document` · `telemetry` · `strings` · `event` -(catalog: `schemas/data_catalog_v2.yaml`). +Published type ids: `size_256` (256 B) · `size_4096` (4 KiB). +Older experiment folders still use `message` / `document` (same lengths). +Catalog: `schemas/data_catalog_v2.yaml`. ## Files | File | Purpose | |------|---------| -| `smoke.yaml` | CI / quick sanity (`message`, n=1, SPSC) | -| `default.yaml` | Publication matrix (all five types × [100, 1000], SPSC+MPMC) | +| `smoke.yaml` | CI / quick sanity (`size_256`, n=1, SPSC) | +| `default.yaml` | Publication matrix (256 B and 4 KiB × [100, 1000], SPSC+MPMC) | ## Usage diff --git a/config/library/default.yaml b/config/library/default.yaml index cf99f92..82a3bc9 100644 --- a/config/library/default.yaml +++ b/config/library/default.yaml @@ -1,18 +1,12 @@ # Run config: default (publication matrix) id: default -description: "Five payload types × [100, 1000] items; SPSC, 2P2C, 1P4C, 4P1C, 4P4C" +description: "Two payload sizes (256 B, 4 KiB) × [100, 1000] items; SPSC, 2P2C, 1P4C, 4P1C, 4P4C" data_model_version: 2 types: - - type_id: message + - type_id: size_256 type_config: {} - - type_id: document - type_config: {} - - type_id: telemetry - type_config: {} - - type_id: strings - type_config: {} - - type_id: event + - type_id: size_4096 type_config: {} data_type_instance_count: [100, 1000] diff --git a/config/library/smoke.yaml b/config/library/smoke.yaml index 822401e..6305864 100644 --- a/config/library/smoke.yaml +++ b/config/library/smoke.yaml @@ -1,10 +1,10 @@ # Run config: smoke (CI / fast path) id: smoke -description: "Minimal matrix — message payload, single instance, SPSC only" +description: "Minimal matrix — 256-byte payload, single instance, SPSC only" data_model_version: 2 types: - - type_id: message + - type_id: size_256 type_config: {} data_type_instance_count: [1] diff --git a/dashboard/index.html b/dashboard/index.html index 784871e..d1409bc 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -96,9 +96,9 @@ - Data type: + Payload size:
-
@@ -151,7 +151,7 @@