@@ -39,10 +39,13 @@ local stateSchema = {
3939
4040local entityCodec = Lync .struct (entitySchema )
4141local entityArray = Lync .array (entityCodec )
42+ local entityDeltaArray = Lync .deltaArray (entityCodec )
4243local boolArray = Lync .array (Lync .bool )
4344local cframeArray = Lync .array (Lync .cframe ())
4445local stateCodec = Lync .struct (stateSchema )
4546local stateDelta = Lync .deltaStruct (stateSchema )
47+ local positionMap = Lync .map (Lync .int (0 , 1023 ), Lync .vec3 )
48+ local positionDeltaMap = Lync .deltaMap (Lync .int (0 , 1023 ), Lync .vec3 )
4649
4750-- Generators -------------------------------------------------------------
4851
@@ -242,6 +245,14 @@ local wireCases = table.freeze({
242245 }),
243246 value = { a = true , b = false , c = true , d = false , tier = 7 , level = 99 },
244247 },
248+ -- zint and delta scalars are stateful for the delta variants; the
249+ -- single-value wire size below is the FIRST-frame size.
250+ { label = "zint(0)" , codec = Lync .zint (), value = 0 },
251+ { label = "zint(95)" , codec = Lync .zint (), value = 95 },
252+ { label = "zint(-96)" , codec = Lync .zint (), value = - 96 },
253+ { label = "zint(1000)" , codec = Lync .zint (), value = 1000 },
254+ { label = "zint(-1000)" , codec = Lync .zint (), value = - 1000 },
255+ { label = "zint(i32_max)" , codec = Lync .zint (), value = 0x7FFFFFFF },
245256})
246257
247258-- Delta wire-size catalogue ----------------------------------------------
@@ -258,9 +269,67 @@ stateMultiMut.velY = 5
258269stateMultiMut .velZ = 6
259270
260271local deltaCases = table.freeze ({
261- { label = "delta unchanged" , seed = stateBase , value = stateBase },
262- { label = "delta 1-field-mut" , seed = stateBase , value = stateOneMut },
263- { label = "delta 6-fields-mut" , seed = stateBase , value = stateMultiMut },
272+ { label = "deltaStruct unchanged" , codec = stateDelta , seed = stateBase , value = stateBase },
273+ {
274+ label = "deltaStruct 1-field-mut" ,
275+ codec = stateDelta ,
276+ seed = stateBase ,
277+ value = stateOneMut ,
278+ },
279+ {
280+ label = "deltaStruct 6-fields-mut" ,
281+ codec = stateDelta ,
282+ seed = stateBase ,
283+ value = stateMultiMut ,
284+ },
285+ {
286+ label = "deltaInt unchanged" ,
287+ codec = Lync .deltaInt (0 , 1000000 ),
288+ seed = 12345 ,
289+ value = 12345 ,
290+ },
291+ {
292+ label = "deltaInt small-mut(+1)" ,
293+ codec = Lync .deltaInt (0 , 1000000 ),
294+ seed = 12345 ,
295+ value = 12346 ,
296+ },
297+ {
298+ label = "deltaInt large-mut" ,
299+ codec = Lync .deltaInt (0 , 1000000 ),
300+ seed = 12345 ,
301+ value = 999999 ,
302+ },
303+ {
304+ label = "deltaVec3 unchanged" ,
305+ codec = Lync .deltaVec3 (- 1000 , 1000 , 0.01 ),
306+ seed = Vector3 .new (50 , 60 , 70 ),
307+ value = Vector3 .new (50 , 60 , 70 ),
308+ },
309+ {
310+ label = "deltaVec3 small-mut(+0.1 stud)" ,
311+ codec = Lync .deltaVec3 (- 1000 , 1000 , 0.01 ),
312+ seed = Vector3 .new (50 , 60 , 70 ),
313+ value = Vector3 .new (50.1 , 60.1 , 70.1 ),
314+ },
315+ {
316+ label = "deltaCFrame static" ,
317+ codec = Lync .deltaCFrame (- 1000 , 1000 , 0.01 ),
318+ seed = CFrame .new (10 , 20 , 30 ),
319+ value = CFrame .new (10 , 20 , 30 ),
320+ },
321+ {
322+ label = "deltaCFrame pos-only" ,
323+ codec = Lync .deltaCFrame (- 1000 , 1000 , 0.01 ),
324+ seed = CFrame .new (10 , 20 , 30 ),
325+ value = CFrame .new (10.5 , 20 , 30 ),
326+ },
327+ {
328+ label = "deltaCFrame full pose" ,
329+ codec = Lync .deltaCFrame (- 1000 , 1000 , 0.01 ),
330+ seed = CFrame .new (10 , 20 , 30 ),
331+ value = CFrame .new (11 , 21 , 31 ) * CFrame .Angles (1 , 0 , 0 ),
332+ },
264333})
265334
266335-- Round-trip catalogue (CPU only) ----------------------------------------
@@ -325,10 +394,80 @@ local blinkCases: { NetCase } = table.freeze({
325394 ),
326395})
327396
397+ --[[
398+ Pool builders for the new delta workloads. Each returns a frozen list
399+ of POOL_SIZE values forming a realistic mutation stream so the bench
400+ measures steady-state cache behavior, not first-frame FULL cost.
401+ ]]
402+ local function poolEntityArrSparseMut (): { { any } }
403+ -- Stable array shape; 3 random indices flip per frame to exercise PATCH.
404+ local current = entityArr (ENT_COUNT )
405+ local p = table.create (POOL_SIZE )
406+ p [1 ] = table.clone (current )
407+ for frame = 2 , POOL_SIZE do
408+ for _ = 1 , 3 do
409+ local idx = rng :NextInteger (1 , ENT_COUNT )
410+ current [idx ] = entity ()
411+ end
412+ p [frame ] = table.clone (current )
413+ end
414+ return table.freeze (p ) :: { { any } }
415+ end
416+
417+ local function poolPositionMap (): { { [number ]: Vector3 } }
418+ -- 200-entry map; ~5 keys mutate per frame to exercise DIFF.
419+ local current : { [number ]: Vector3 } = {}
420+ for i = 1 , 200 do
421+ current [i ] = Vector3 .new (rng :NextNumber (- 100 , 100 ), 0 , rng :NextNumber (- 100 , 100 ))
422+ end
423+ local p = table.create (POOL_SIZE )
424+ p [1 ] = table.clone (current )
425+ for frame = 2 , POOL_SIZE do
426+ for _ = 1 , 5 do
427+ local k = rng :NextInteger (1 , 200 )
428+ current [k ] = Vector3 .new (rng :NextNumber (- 100 , 100 ), 0 , rng :NextNumber (- 100 , 100 ))
429+ end
430+ p [frame ] = table.clone (current )
431+ end
432+ return table.freeze (p ) :: { { [number ]: Vector3 } }
433+ end
434+
435+ local function poolPositionStream (): { Vector3 }
436+ -- Continuous motion: + ~0.5 stud per axis per frame. Hot path for deltaVec3.
437+ local current = Vector3 .new (0 , 0 , 0 )
438+ local p = table.create (POOL_SIZE )
439+ for frame = 1 , POOL_SIZE do
440+ p [frame ] = current
441+ current = current
442+ + Vector3 .new (
443+ rng :NextNumber (- 0.5 , 0.5 ),
444+ rng :NextNumber (- 0.5 , 0.5 ),
445+ rng :NextNumber (- 0.5 , 0.5 )
446+ )
447+ end
448+ return table.freeze (p ) :: { Vector3 }
449+ end
450+
451+ local function poolCFrameStream (): { CFrame }
452+ -- Walking-character pose: position drifts, rotation slowly turns.
453+ local pos = Vector3 .new (0 , 0 , 0 )
454+ local yaw = 0
455+ local p = table.create (POOL_SIZE )
456+ for frame = 1 , POOL_SIZE do
457+ p [frame ] = CFrame .new (pos ) * CFrame .Angles (0 , yaw , 0 )
458+ pos = pos + Vector3 .new (rng :NextNumber (- 0.3 , 0.3 ), 0 , rng :NextNumber (- 0.3 , 0.3 ))
459+ yaw = yaw + rng :NextNumber (- 0.05 , 0.05 )
460+ end
461+ return table.freeze (p ) :: { CFrame }
462+ end
463+
464+ local positionsCodec = Lync .deltaVec3 (- 1000 , 1000 , 0.01 )
465+ local cframeStreamCodec = Lync .deltaCFrame (- 1000 , 1000 , 0.01 )
466+
328467--[[
329468 Extended workloads at 100 fires/frame. Pairs vary/stable cases on the
330469 same codec to expose XOR + delta savings: vary = worst case, stable =
331- same array reused so XOR collapses, delta = single field flipping .
470+ same array reused so XOR collapses, delta = sparse mutations .
332471]]
333472local extendedCases : { NetCase } = table.freeze ({
334473 defCase (
@@ -345,6 +484,7 @@ local extendedCases: { NetCase } = table.freeze({
345484 return entityArr (ENT_COUNT )
346485 end )
347486 ),
487+ defCase ("entity_deltaArr_100__3mut" , entityDeltaArray , poolEntityArrSparseMut ()),
348488 defCase (
349489 "bool_arr_1000__vary" ,
350490 boolArray ,
@@ -362,6 +502,10 @@ local extendedCases: { NetCase } = table.freeze({
362502 ),
363503 defCase ("state_full__vary" , stateCodec , poolVarying (stateOne )),
364504 defCase ("state_delta__1mut" , stateDelta , poolStateOneMut ()),
505+ defCase ("position_map_200__5mut" , positionMap , poolPositionMap ()),
506+ defCase ("position_deltaMap_200__5mut" , positionDeltaMap , poolPositionMap ()),
507+ defCase ("vec3_walking_motion" , positionsCodec , poolPositionStream ()),
508+ defCase ("cframe_walking_pose" , cframeStreamCodec , poolCFrameStream ()),
365509})
366510
367511-- Handshake --------------------------------------------------------------
0 commit comments