Sharpify.Data
2.5.0
See the version list below for details.
dotnet add package Sharpify.Data --version 2.5.0
NuGet\Install-Package Sharpify.Data -Version 2.5.0
<PackageReference Include="Sharpify.Data" Version="2.5.0" />
paket add Sharpify.Data --version 2.5.0
#r "nuget: Sharpify.Data, 2.5.0"
// Install Sharpify.Data as a Cake Addin #addin nuget:?package=Sharpify.Data&version=2.5.0 // Install Sharpify.Data as a Cake Tool #tool nuget:?package=Sharpify.Data&version=2.5.0
CHANGELOG
v2.5.0
- Updated to use version 2.2.0 of
Sharpify
and later, andMemoryPack
1.21.1 and later. - Removed apis that were previously marked as
Obsolete
- An overload with
ReadOnlySpan{byte}
was added toUpsert
, enables usingUpsert
on other types, such as lists or even pooled arrays. Be careful when using thebyte[]
overload, as now it doesn't create copies and instead inserts the reference instead to improve performance where needed. DO NOT USE this overload with buffers which you only temporarily own, for those use the newReadOnlySpan{byte}
overload. UpsertMany<T>
now also has aReadOnlySpan{T}
accepting overload, it will not improve performance, but still adds flexibility, it doesn't replace the originalT[]
overload, it is an alternative. If the mainT[]
suits your context, as in you already have a fixed size array, it will actually be more performant.- New method
Database.TryReadToRentedBuffer
now rents an appropriately sizedRentedBufferWriter{T}
and attempts to write the value to it, then return it. If it is successful, the result can be viewed withRentedBufferWriter{T}.WrittenSpan
and other apis, if not successful (i.e key not found), a disabledRentedBufferWriter{T}
will be returned, it can be checked with theRentedBufferWriter{T}.IsDisabled
property.- There is also an optional parameter for
reservedCapacity
, this will make sure the buffer has a matching amount free capacity after writing the data, an explanation of why this is useful will be lower down the page. - There are overloads in
Database
for bothbyte
andT : IMemoryPackable{T}
, as well as methods inMemoryPackableDatabaseFilter{T}
andFlexibleDatabaseFilter{T}
.
- There is also an optional parameter for
- POSSIBLY BREAKING for those who use the
JSON
serializedT
overloads, in the previous versions, theJsonSerializer
was used to generate astring
, which then passed toMemoryPack
for secondary serialization. To improve performance, nowJsonSerializer
directly serializes tobyte[]
which means using these types is now both faster and more memory efficient than before. But if you try to read values with the new version which were serialized in the old version, there may be inconsistencies which may cause errors.- If you encounter such issues, you may want to synchronize manually as follows:
- Read the values with
TryGetString
, then useJsonSerializer.Deserialize
on the strings to get the actual values, you can then proceed to upsert those values with theJSON
overloads on the same keys.
- Some of the new changes were also leveraged internally to improve performance/memory allocations in various places.
New APIs: Purposely Built For Performance
Upserting a ReadOnlySpan
instead of []
, or reading data into a RentedBufferWriter
may seem unnecessary by themselves, but using both together can unlock the next level of performance in some scenarios.
Consider the following example:
you have a server which manages some items of different categories, and you use a collection to hold items of type book
for example, and a request comes in to add a new book.
Before this change
- Retrieve allocated
Book[]
- Allocate a new
List<Book>
- Copy said
Book[]
toList<Book>
- Add new book at the end of said
List<Book>
- Copy
List<Book>
to a newBook[]
- Upsert said
Book[]
This means for N
books, we allocate 3N
items, this is a big waste...
After this change
- Retrieve
RentedBufferWriter{T}
usingTryReadToRentedBuffer
withreservedCapacity=1
to add 1Book
- Insert new
Book
withRentedBufferWriter.WriteAndAdvance(Book)
- Upsert with
RentedBufferWriter.WrittenSpan
Firstly this is so much simpler, secondly, the performance gains are huge, RentedBufferWriter
as per the name uses array pooling, in this scenario you don't need the actual array, so this is the perfect place for them, so we write to a pooled array, which has enough reserved capacity, which we use to add the book, upsert the written portion, and after this usage RentedBufferWriter
which implements IDisposable
automatically returns the array to the array pool.
Reminder: Workaround for broken NativeAot support from MemoryPack
As of writing this, MemoryPack's NativeAot support is broken, for any type that isn't already in their cached types, the MemoryPackFormatterProvider
uses reflection to get the formatter, which fails in NativeAot.
As a workaround, we need to add the formatters ourselves, to do this, take any 1 static entry point, that activates before the database is loaded, and add this:
// for every T type that relies on MemoryPack for serialization, and their inheritance hierarchy
// This includes types that implement IMemoryPackable (i.e types that are decorated with MemoryPackable)
MemoryPackFormatterProvider.Register<T>();
// If the type is a collection or dictionary use the other corresponding overloads:
MemoryPackFormatterProvider.RegisterCollection<TCollection, TElement>();
// or
MemoryPackFormatterProvider.RegisterDictionary<TDictionary, TKey, TValue>();
// and so on...
// for all overloads check peek the definition of MemoryPackFormatterProvider, or their Github Repo
Note: Make sure you don't create a new static constructor in those types, MemoryPack
already creates those, you will need to find a different entry point.
With this the serializer should be able to bypass the part using reflection, and thus work even on NativeAot.
P.S. The base type of the Database is already registered the same way on its own static constructor.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net7.0
- MemoryPack (>= 1.21.1)
- Sharpify (>= 2.2.0)
-
net8.0
- MemoryPack (>= 1.21.1)
- Sharpify (>= 2.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.6.0 | 79 | 11/13/2024 |
2.5.0 | 83 | 7/30/2024 |
2.4.1 | 84 | 6/3/2024 |
2.4.0 | 82 | 5/30/2024 |
2.3.0 | 125 | 4/17/2024 |
2.2.0 | 132 | 3/2/2024 |
2.1.3 | 114 | 1/25/2024 |
2.1.2 | 103 | 1/25/2024 |
2.1.1 | 107 | 1/25/2024 |
2.1.0 | 127 | 1/25/2024 |
2.0.2 | 103 | 1/23/2024 |
2.0.1 | 104 | 1/22/2024 |
2.0.0 | 99 | 1/20/2024 |
1.1.0 | 116 | 1/15/2024 |
1.0.3 | 125 | 1/8/2024 |
1.0.2 | 130 | 1/5/2024 |
1.0.1 | 124 | 1/4/2024 |
1.0.0 | 120 | 1/4/2024 |