2,214 Commits over 549 Days - 0.17cph!
Update: Migration to "unsafe" FreeUnmanaged - Interface Code
This CL contains all cases where we call FreeUnmanaged with T : interface - this is dangerous because we don't know whether T is IPooled or not. If/when in the future we make FreeUnmanaged to skip invoking OnPoolEnter, this will lead to leaks/bugs.
Tests: Built all targets.
Update: Migration to "unsafe" usage of FreeUnmanaged - Generic Code
These cases are part of generic code that either provides containers/algos for other parts of logic or part of currently-dead code. They're unsafe because if they start getting used with T : IPooled, then in the future if/when we change Unmanaged to not check IPooled it might leak/bug out.
Tests: Built all targets.
Update: New CodeGenerator for Pool.FreeUnmanaged<MemoryStream> change
* CodeGenerator built with a3cd77f3 from FreeList-Depr branch
* This replaces all uses of Pool.FreeMemoryStream in Rust.Data/generated/ProtocolBuffers.Serializer.cs
Tests: built all targets in editor.
Update: Updating ProtoBuf Codegen to use new Pool API
* Includes new debug CodeGenerator binaries(built from FreeList-Depr branch, commit 1874d134). RustProtoBuf will be merged to main once I get closer to completion of teh refactor.
* Generated new Rust.Data/generated/*.generated.cs files with no FreeList calls
Tests: build tests for all targets
Update: Constraining Pool.Free - Step 2
* Adding collection-related FreeUnmanaged overloads for all existing collection-related Free overloads
* Putting IPooled constraint on almost-all collection-related Free overloads (skipping List - that'll be next chonky CL)
* Changed StreamBuffer overload to be a FreeUnmanaged overload
Tests: built all targets in unity
New: Adding Facepunch.Tests assembly for unit testing Facepunch libs, with ListExtension tests
Motivation: when working on core libraries we gotta have confidence that we won't bork something somewhere by changing core algos&utils. With this test assembly, we have a common place to document behavior of Facepunch lib before we go modify it.
Added 64 test cases for ListExtension changes (I couldn't reliably confirm in 3p multiplayer session). Test assembly configured in lean fashion.
Tests: built all targets in editor. Ran all existing tests, including new ones being submitted. Observed ~10 failures in NavMesh and TextMeshPro, but new tests pass.
Optim: reimplementing List.Compare to use an inplace algorithm
Caused by my upcoming changes to Free<HashSet<T>> requiring IPooled(I could've worked around it, but it was better to optimize it). Although I didn't benchmark, this in theory is a straight win - 3 less loops, no need for extra pools, and also fixes a harmless-but-perf bug(remained set had more elements than expected).
Tests: Build for Client target. I also need to do runtime validation with a 3player multiplayer session - I ran out of time, will done once I'm back home.
Update: Adding Pool.FreeUnmanaged overload for MemoryStream
Since Free got changed to accept IPooled only, it allows us to delete a runtime check in the editor env.
Tests: build only in editor, all targets
Feedback: Replacing bikeshedded emptyArray with Array.Empty<T>
Tests: trivial change, so only built Client+Server
Update: Constraining Pool.Free - Step one
* Primary Pool.Free overload now only accepts IPooled types
* Secondary overloads added to work with collections (not restricted to IPooled yet). They all call Clear() on the returned pooled container.
* Pool.FreeList now just pipes to one of Pool.Free secondary overloads (proper cleanup will be done later - there's 800 occurances of FreeList usage)
* Added Pool.FreeUnmanaged as an escape hatch for types that are in the pool but don't implement IPooled interface.
Motivation: If we want to avoid leaking memory and reduce potential of "improperly-recycled" pooled objects, so we need a more controlling API for Pool that allows users to avoid misusing it and calling the wrong API by accident. We'll get there by providing a stricter API that checks for users whether it's legal to use it in a particular way. This means I have to write a bunch of boilerplate (overloads + variations) and clean up all the use cases we have(both the types that might benefit from IPooled and all the API usage points).
Tests: built all targets for scripts in editor. Didn't do any runtime testing as there's only 1 safe functional change (clearing of collection on return to pool).
Clean: Nuking SimpleList.cs
Nothing uses it anymore, and it's superseeded by BufferList.
Tests: All targets in editor built succesfully
Update: Replacing SimpleArray uses with BufferList. BufferList also avoids allocations when default-constructed.
There's 2 reasons for this change: they're functionally the same(with a small change for default BufferList), but BufferList offers more. Also, and the primary reason, it allows me to refer to the type at a lower assembly level (Facepunch) so that I can continue making Pool's API more strict.
Tests: checked all "targets" build in Unity, no runtime tests (well, editor runs this code outside of playmode as well, so there's that)
Update: Inlining PoolCollection::Fill implementation into Pool
In order for us to unify TakeX/FreeX custom methods into a single overload set, we need to unify their constraints. This removes one new T() call from 2 calls in PoolCollectionm which is first step towards removing new() constraint on PoolCollection(and instead preserving it on Pool APIs).
Also left a note about thread safety - luckily right now everything is used in a safe manner
Simplification: avoid double hash calculation when pushing new elements into the Pool in editor