Max: Faster buffer -> list

If folk are peeling buffers out into lists a lot, using peek~ is pretty suboptimal beyond a few values. I’ve started an abstraction using jit.spill instead, hopefully of some use (although for some reason jit.spill is internally limited to 16384 values, rather than Max’s limit of 32768)


----------begin_max5_patcher----------
1407.3oc0Zs0SiiCE941eEV4IPpT4Kw4B6K759vp8GvnQnzVSInbSINLEMZ1
e6qsOIPCMkDHNUyffVriSO9663y0zetbgyl7ChJGzsnugVr3mKWrvLkdhEMi
W3jFcXaRTkYYNaySSEYRmUv0jhCRy7+asrnVhRhqjneDKeDcUU8lJgDk+v0n
M0O7fnDsMOSptWT6MWIeIQXt61YxpSiyRDRirHMSVDI29Xb196KEakvdk5wW
iWgb8MuQogl2vqwnu+1mTdsr8iB2La7Ni3x27zM9DG8b+Z4R8KqlH7+6LE5u
EsIJauBlEwhpVPKyMjxegpjQkRTT1NjP8WbFpJJsHQTotxKoaxSzqTSXv8YM
NhvLLEk9EnHrMonmhkqqJhSRPQak0QIIuf1lDWTAmYRDY6UmZTb.wiE3htJR
OWj5JJl5ehNf7uFc6MWg9Vr5LTYVTB5wnxcp6MMVsjJDi56EbcqPShyDayqy
LR1cxTIC6YHQLvnbyHuOEW5E7U3xLwOT27IT4Msy.xT9Rg.1nNwZH+8wAX5G
.XBbbwyXXQvLvL6H.uMOIuDVLdsqZM5Uz9emgVH8PKdSmVdNRcdHE.ZMCSvp
eI3SHMELkkn61DmsSaoosFOKM5rp4uwxkezgmPywEpKF3xvA4R75fFB87bI6
TtjG1t0JEUx7xFvvbeCDQOK1cuZspM28Z5HdSsD7+u3UpVChREepLytWjEsA
fM1bMidxRGhkn8B4CZIobA7wZBKnE.+eDOya99VQGP6QGXSy7hRQgNVQtI15
.mXs.GQXf4NyXtSHbqvR8X06xrqUeUdc4VwYr3gKhtSSVMgZ6MLA8R3L.NFF
3CtBb0uw312UfKsWWAGCgeCbEbrJDh+eFUXSxAfJLIOa+EwwsKI73ffL9b43
lw6Uag+sUY0wUz6M2Lo4dpp5xaq03NCL1BmMaMl6eTgcMZoGq2L6QbccIGEM
gymqPtLliUYmsOJJiJ2WgtqMxQyQ5ttnlOdCJuHnIGE5rwaXKxakJYIfxeA1
pwkc2Hym2b+yZ1yGrt2lXr93S3utLC+TlgFNCIwoJseVSdqIAWvZy2ctRci9
kRv0ffoCe7fZcVf4Ub6qeBf467JSAMv33sgpnQwgWcH+IQOHX600KnMDCBxd
5BA0a1.4YqxCpd4sh8N6w.XgVKS611eAEyf+vR9dq6ECzBid7iR4yVIeCEww
Fcm.5zCiZLbHT24pSODeKRSJrEmVmZ55m+G1LrUVumXgP4.TOqvT8bfh3Y8.
yCX48or4FAEAs5xOX1XHaZx8VeouS2I5lDWL8Sd96JUSTK34XPbYykSJuigc
GsPHkv8B0elgDeOWey+wz+zHB6xzvS23+NKypVy8oQpRjNn43tirHiSIlind
dVgv6opPpUHbi7LkN+tGRmAY546pEZR2tIdJze8UG0HgcpJTiyhjw4YGsHRy
h5USOZIMBAQsgfzs4dPIYvMYpRJXLXpyZFWV1ow6JxUgkpZcatlqVPHbxTk6
d6Har+Iy+9OHzriUUbwea+qGMw8uK6xv+D2.XKi6..7zA.cL.HvBFE5VHNN6
7oZTna20fRpUyMMIgGwwWFa55eOOP+SMwDb43WGMQDPCuPHPm3E0roocf.0N
PfdIf.Gd9nD+iQfdjMP.6Rf.kKOeyll0ABL6.gA8ivOGD5KOloseFSfQtM7q
o6JyvHO7xgb9TBIMOamoEgu+Rvd+QaOJDSrSJJASOEkwDfzFIMRGgWLB2BBh
3O4bVFmFgZRZjAegF3PgLcGQfm40qIT5NYsEYTUS3aCZjO1j76qfonhhmEkU
Mq1HDUApOArr+Jyv3LXno1MmRwywsq278EyIpTU5nTU2XM7D8bND.EQ6jluS
TlUGapzboVx+Z4+idIJFw
-----------end_max5_patcher-----------
1 Like

That is super handy!

(quite tidy patching too!)

Can be useful too for certain contexts where you need to do data processing that falls outside of the fluid. universe.

edit: out of curiosity, what are you calling the abstraction? Perhaps it could be useful to include it in the distribution? (fluid.spill~?)

Ooh, that’s a good idea. It’s saved currently as the far less pithy fluid.buf2list. I shall proffer unto my team mates and see if it makes the cut :wink:

1 Like

Is there an easy way to test if it clips in Max8 (not that it matters, given the scope of the project), to see if it’s worth flagging it up as a bug to c74?

Looks like it remains the case in 8 as well (I checked with framelib as well, to make sure it wasn 't zl len). There’s also a big boo-boo in the patch (route instead of routepass):


----------begin_max5_patcher----------
1406.3oc0ZsraaiCEcs8WAgVkB3XvGh5QlMY6rXv7ATTDHay3n.8BRToNnny
29PxKUhUibrRDkQaQiUHEku7btu38p7ikK71TdPz3gtA8UzhE+X4hElozSrv
NdgWdxgsYIMlk4ssLOWTH8VA2SJNHMy+usxpVIJKsQh9dp7AzUMsaZDRT48e
Aso896E0nskER0yh5d3F4yYByS2MSQadZQlPZjEwNYUhb6CoE6uqVrUB6UZ.
eMdExOzbgRiMWvqwnu852TYqr6qBamMcmQbkad75Phmdtetbo9iUSD9+cgB8
2f1jTrWAypTQSGnkkFR4uPMxjZIJoXGRn9Is.0jjWkIZT2447MkY5UpIL34b
FGQXFlhR+DTD1kTziox0MUoYYnjsx1jrrmQayRqZ.alLQwdkUihCHArHezUI
54RT2QwT+SxAT3WP2b8UnulprgpKRxPOjTuS8r4opkzfXzvfnuzIzrzBw1x1
Bij8mLUxvAFRDCLJ2LJ3CwkAQeFtrP7c0C+Fp75tY.YJetR.aTuTMj+13.L8
c.LALWBLNVDLCbyNBvaKyJqgEiW6qVidEc+1InEx.zRvzokmRT1C4.PaYXBV
8eB9MjlBlxZzsaRK1o8zzdimjF8VY+Yrb46Y7DaLWn9XfKiOKWhWGYIzSykr
2xk73tsVsnQVVaACy+UPj7jX2cp0p1b2ooizMsRH9+hWnZMHpU7oxM6NQQxF
.1Xy8L5IGYDKQ6Ex60RREB380DNPK.w+HAlKggNQGPGPG3R27pZQkNWQoI25
YrXc.GQXf6Ny3tSHbmvRC306ybqWeSYa8VwI73gahtUSV1TsCllfdIBF.lgQ
gPn.e8EF28gB7oCFJ3XH7aPnfiUgP9+SnBsGN.TgYkE6uHAt8IwGmDjwmq.2
L9fZK7usJqdgh9U2Mywbeqp5x6qYCmANawyluFy+OpztFszCsal8Lt99jixl
v4yUJWFyyory1GD0I06aP21k4vZR2OD07wagGkifZqaaN3MrC4sZkrDUpEAk
.CLlMrc+rym1k+i55yOasu17rwu01qO6veK6PimgCxoJueVO.m8PtfGWn+bc
7M5m5PtFDLc3iOqVmEY9D284G.XgduvTPSLNdanJbTb3kfxePzCB1cc9BZEw
YA4.chfFLaf7jU5AUv7ZAemzL.VnyNscWKvfBZvuaYeu1AiyzFiAhkR4yVYe
mKqiK5PAzsGF033Pn9yU2dHgNjlTXKMuM2z4uv2sgXqbdewhgRBnANgoFvfh
D35jyny348g74FAEAs6JLZ1XHW5x8ZuouU2MZ6AWL8Td96LkMqE7tLH9r4JH
UvwvtmVHlR3Aw5uyXRXfen42X5+YEgaYZ3Mb7emjYUq4t7DUYRGzbb+QNjwo
DiIZPfSH7ApLj5DB2HOS4y+xKpyfL8780B1iaaymZOUyQMSXmpJ0zhDYZYww
KJt2hNCCLn8vn2OwiY+vur6G1Y1OppLOw94cNIcd5tpRUpGqhyGGrlqarJ7J
433WF4BDPu.HfEPg8bXODD5FDPtDHfDY1yPoRcH.79mDBBBFgUMwtnoIow39
3BAwGiipA2joJonwfIWn8MpaaCATUH2MxE6ex7u+ihM63nP8kt8udzD2+9rK
C+S7AuuHbO.fmN.niA.QNvofwGqe9TcJzMV9rRpSyMMIguPQeCh.MNE2K5Kd
54OFS.DtKz+T9TbUb+gW3SNxyvEfchL+Q8BcFM8Pmiww0EIyni3HRDtCDDIb
xwRGmFgZRlwf+jF3PYL8GQf250KI57mr1hLpS4D5BZjO1CeLT4RIUUOIparq
1HDU4oOBrb3JyvzBXnoxMuZwSocq27WLlWRspvQoppwV3c54cHBJg1Kubmnt
nM0Tm4Rsj+4x+GHvUjsA
-----------end_max5_patcher-----------
1 Like

I guess worth submitting a bug report thing? Especially since c74 is good about fixing Max bugs (right (right!?)?).

1 Like

I think we should keep it buf2list, because @rodrigo.constanzo are likely to ask for buf2dict as another type of spill soon…

1 Like

Possibly worth a shot. I’m sure JKC has a rationale for why it’s 16384. Perhaps @a.harker already knows, for he knows many things…

Meanwhile, I’ll need to think about how to beef up this abstraction to deal with multichannel stuff flexibly.

My thinking for dict is that once you have a list, it’s pretty simple to insert that into a dict. Moreover, people will know where in the hierarchy they want it placed: I don’t see an abstraction that could use fewer objects than a set message into dict, but maybe I lack imagination :wink:

I thought that dicts would be good to go beyond the 16k entry count… and make readable entries… and all the magic I’m promised, like world peace and fast queries…

They smell like flowers too.

But sadly they are slow with large data sets, in a way that @a.harker clearly pointed out to them a while back.

That being said, I haven’t really speed tested dict in Max8 yet.

dicts use a hash table but it is too small to give decent speed. Please feel free to bug c74 about that more, but you won’t get fixes in old versions of max.

I’d probably vote for buf2coll. Coll is a linked list, so pretty slow, but really large dicts are basically just as slow.

1 Like

would it not be better to have fluid.spill~ @type dict/coll/list :slight_smile: ?

2 Likes

@weefuzzy

1: Is pattr just for neatness?
2: Is there an overhead in the patch for using pattr over just pushing the values straight in?

That, and it makes your patch pattr-able.

Very slightly, as there will be a lookup and a function call. Not enough to worry about in this case.

Fair dink, I really like the colours :slight_smile: Very easy to understand! I wonder how fast fl.read~ is in comparison!

To me, all these different containers have different utility, and list is the most foundational: I tend to do an awful lot of my Max work in lists, and dicts when I need something more structured. So, it makes sense to me to at least start with lists.

The other two types require more user input (which coll? where in the dict?)

Seeing as y’all being helpful with feature suggestions, you can help me figure out an interface for all that :wink: As well as what buf2list should do with multichannel buffers

For naked reading with no interpolation, I’d imagine that they’re comparable, but hard to measure given that the framelib stuff is always being triggered on the audio thread, and the jitter stuff isn’t.

I’d probabbly try a Javascript example to see how faster it is than all of this. It could do to list, coll and dicts :wink: - I’ll do that if no one has done it as soon as I can release alpha06a

Although, kind of useless in real-time because js runs in low prior thread :frowning: