2,670 Commits over 669 Days - 0.17cph!
Update: add debug only sentinel writing to playerInfos and playerSegments
Tests: ran unit tests
Bugfix: fix tick being written to an index that didn't account for growth
Tests: all unit tests pass
Update(tests): add TestTickGrowth2Players that also validates tick consistency after growth
Tests: ran new test - fails as expected
Bugfix: avoid out of bounds read when growing array due to tick capacity exhaustion
Tests: ran unit tests - no more failures (but there's an extra known bug)
Bufix(tests): TestTickGrowth - ensure all ticks are interpolated by picking a better reset point
Tests: ran unit test
Update(tests): Adding TestTickGrowth - accumulates ticks past capacity
This one catches out of bounds read during growth (but not the one expected)
Tests: ran unit test
Update(tests): add TickInterpolatorCache stress unit test
Slams 10k operations on it(add/remove player, move player, reset) - doesn't catch issues
Tests: ran new test
Buildfix: missing files from previous submit
Clean: minor reaorganization + comments
Tests: unit tests
Clean: store buffer[pos] accesses in a variable
Just for easier code reading
Tests: ran unit tests
Clean(editor): get rid of Pool.UseSafetyChecks flag
- lock-free Pool can't ensure associated hashset consistency, so we can't use that anymore
- checking for null on Take call doesn't seem to make sense since awhile back
Tests: ran tests. StressTestMT doens't sporadically fail anymore
Optim: couple micro optims
- rewrite a couple branches into branchless logic
- inlined IsTurnTicketSameIgnoreProgress
- got rid of module via use of MADD
- added extra comments for explaining what's going on
AllocDeallocST: 2.82 -> 2.77ms for 10k allocs. Tiny, but every bit helps
Tests: ran unit and perf tests
Update: replace member variables with cacheline sized counterparts
Didn't see any notable change in perf tests, but wouldn't hurt
Tests: ran tests
Update(tests): add a couple tests
- Perf: AllocDeallocMPSCAtomicCounter
- Unit: TestAllocWhenEmpty, TestFreeWhenFull
Tests: ran tests
Update: resubmit original pool mutex implementation in a separate branch
Makes it easy to test across extra benchmarks
Tests: ran unit and perf tests
Bugfix: rewrite fuzzy circular buffer to prevent gradual poisoning of the pool (hurt my brain)
Lost a bunch of perf(loses a bit to CircularBuffer in some tests, wins in others), but the spills are now minimal.
AllocDeallocST - Avg: 0.79ms, Created: 0 Spilled: 0
AllocDeallocMTShortLived - Avg: 4.03ms, Created: 22(0.07%) Spilled: 25(0.08%)
AllocDeallocMTLongLived - Avg: 3.84ms, Created: 0 Spilled: 0
AllocDeallocMPSC - Avg: 3.96ms, Created: 0 Spilled: 0
Tests: ran all unit and perf tests.
Update: use volatile int instead of Volatile.Read(ref long), as the latter is an expensive CAS
Existing code was using non-volatile read of long, but I don't think it's safe
Tests: ran perf tests
Bugfix: fix extreme spillage in high-contention perf test
Turns out I needed to do an extra spin, whoops
Tests: ran unit and perf tests
Update(tests): add 4, 8, 16, 32 task scenarios (previously was just 32) for pool perf tests
Tests: ran perf tests
Update(tests): expand AllocDeallocMTShortLived to optionally simulate busywork
We're never going to be just slamming the pool(or if we do - we shouldn't as that's overhead). This makes the test closer to real world.
Tests: ran perf test
Clean(tests): consolidate pool create-spilled code into Utils.MeasureAndPrint
Tests: ran perf tests
Update: fuzzy version of pool with CircularBuffer
Fastest so far, but has a tendency to spill/allocate in during very high contention
AllocDeallocST - Avg: 0.63ms, Created: 0 Spilled: 0
AllocDeallocMTShortLived - Avg: 2.79ms, Created: 144(0.45%) Spilled: 169(0.53%)
AllocDeallocMTLongLived - Avg: 2.94ms, Created: 0 Spilled: 0
AllocDeallocMPSC - Avg: 3.26ms, Created: 0 Spilled: 0
Tests: ran unit and perf tests
Cherrypick from pool_mt/circularbuffer - test improvements
Update(tests): gather and output more data about the test
- track created and spilled (matters for next pool version)
- more profiler markers
Tests: ran perf tests
Update(tests): add a couple more perf tests
- AllocDeallocMT -> AllocDeallocMTLongLived (biases Get, then Free operations), Avg: 3.56901ms
- AllocDeallocMTShortLived - fetches and returns to pool immediately (to evenly spread pressure), Avg: 3.01974ms
- AllocDeallocMPSC - simulates multiple-producers-single-consumer (emulates network write thread under jobs 2) Avg: 12.20773ms
All cases - 32 tasks doing 1k allocs
Tests: ran perf tests
Update: rewrite pool as a circular buffer with 0 locks
Weirdly loses to ConcurrentBag in mono by 2x, but in CLR wins 4x >.> Going to poke around more
ST avg: 0.62554ms
MT avg: 9.92301ms (dafuq?!)
Tests: ran unit and perf tests
Update(tests): AllocDeallocMT perf test scope annotations
Tests: ran perf test
Bugfix: ensure Pool.Fill keeps items in use valid
Tests: ran unit tests
Optim: rewrite Pool to use ConcurrentBag(many mutexes) instead of single mutex
Fails unit tests, but not going to focus on fixing it just yet - want to make it faster first.
ST avg: 0.88781ms
MT avg: 3.1281ms
Tests: ran perf tests
Update(tests): add TestMTPressure unit test
Wrote it cause my ConcurrentBag based pool is misbehaving
Tests: ran new unit test
Update(tests): pool now has a runtime switch to disable editor-only safety logic, so that perf is more apples-to-apples
ST avg: 1.0358ms
MT avg: 13.6264ms
Tests: ran perf tests
Update(tests): add simple pool perf tests (ST & MT)
ST avg: 1.29925ms for 10k alloc-deallocs
MT avg: 21.16116ms for 1k alloc-deallocs per task, 32 tasks
Tests: ran tests
Update: move Utils Measure routines to Facepunch.System.Tests
- also make it auto-referenced
Tests: compiles
Merge: from sanitize_specatating_players
- Bugfix for NRE spam when spectate mods don't correctly setup spectating
Tests: none, trivial change
Bugfix: ServerOcclusion - add defensive checks for suspected spectate mods
The mods should be fixed, but at least it won't put servers in a weird state.
Tests: none, trivial change
▆ ▍▇▆▅▌▋ ▅▌▍▄ ▄▍▅▇▇▍▌▉██▇▄▋▊▅▄▍▄▄█▇▍▆▍▋█▌▌▋▆▋▊▍▋▇▋▌▊ ▅▆▌▊▆ ▇▌▍▉▊▍▌▋▄▋▉▊▅ ▊▅▊▌▄ ▄▌▅▋ ▊▅▄▆█▅▆▍▋▉▊▊ ▍▅▋▍▆▌▍█▊ ▍▇▄▆▄ ▊▍▆▆▌▌▄▉▅▌▉▇▉▊▉ ▄▍▍▍█ ▋▄▌ ▍▌▅▌▋▄ ▋▋ ▍▍██▆▋▉ ▊▌▉ █▍▍█▌▆▇ ▍▊▍█▄▋ ▇▊ ▅▆█▋▄▇█▇▄▉▇▅▅▆▇█ ▆ ▅▌ ▆▅▌▉ ▍▌█▋█▌▆
▋ ▊▊▄▊▍▆▊ ▋▊▆▆▆▊ ▊▋▉▆▉▄ ▇▅▌█▉█▅▇ ▌▆▄▄ ▉ ▆▊▊ ▊▅▊ ▆██▄▋▆▉▇▌▉▍▅█▍▄▅▉▋▆▉▅▋▍▋█▉▅▋▄▍▍▅▇▉▇▉▍▄▄▆▄▅▇▋▌ ▄▊▅█▅ ▄▌█ ▊██▉▊▊ ▆▄ ▋▇▌▉▌▌
Merge: from objectworkqueue_valuetype_allocs
- Optim: eliminate allocs from value types used in ObjectWorkQueue. Needs manual changes to be eneabled
Tests: none, trivial change. Checked IL
Optim: Apply IsValidToRun for value-type ObjectWorkQueues
- overrode BoatAIWorkQueue, UpdateSurroundingsQueue, UpdateMissionValidStateWorkQueue
Tests: none, checked IL
Optim: use virtual IsValidToRun to avoid boxing allocs in ObjectWorkQueue.RunQueue
Sad-noises-about-C#-generics, couldn't figure how to automate it
Tests: none, inspected IL, no box instructions generated
Merge: from createcorpse_triggerparent_nre
- Bugfix for TriggerParent not cleaning themselves up if a corpse forces it's way just before volume is destroyed
Tests: ran auto tests
Bugfix: Ensure TriggerParent properly tracks forced corpse
Corpses forcefully inherit trigger volumes, which doesn't properly initialize internal contents, leading to skipped cleanup when volume is destroyed. Rare bug in the wild, but consistent in auto tests.
Tests: ran all PlayerMountedToArmoredVehicle_PlayerNotTargeted auto tests
Merge: from stableobjectarray_remove_dirty
- Optim: maintain synchronized order of dependent data as we remove from StableObjectCache
Tests: unit tests and a couple 2p sessions on Craggy with disconnects, shooting
Update: codegen
Tests: none