This is an automated email from the ASF dual-hosted git repository.
curth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new dcf0d8ca7c GH-44237: [C#] Use stack allocated buffer when serializing
decimal values (#44238)
dcf0d8ca7c is described below
commit dcf0d8ca7c4bdbeb6f207180017ca9375f15230e
Author: George Vanburgh <[email protected]>
AuthorDate: Thu Sep 26 13:28:07 2024 +0100
GH-44237: [C#] Use stack allocated buffer when serializing decimal values
(#44238)
[Span overrides for
`decimal.GetBits`](https://learn.microsoft.com/en-us/dotnet/api/system.decimal.getbits?view=net-8.0#system-decimal-getbits(system-decimal-system-span((system-int32))))
were added in .NET 5, and allow us to avoid a heap allocation for each decimal
value serialized.
Running a quick benchmark shows the expected reduction in allocations
```csharp
using BenchmarkDotNet.Attributes;
namespace Apache.Arrow.Benchmarks;
[MemoryDiagnoser]
public class DecimalUtilityBenchmark
{
public decimal Value => 1.00000000m;
private byte[] _buffer = new byte[16];
[Benchmark(Baseline = true)]
public void Baseline() => DecimalUtilityMain.GetBytes(Value, 34, 10,
16, _buffer);
[Benchmark]
public void Candidate() => DecimalUtility.GetBytes(Value, 34, 10, 16,
_buffer);
}
```
```
BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.4894/22H2/2022Update)
13th Gen Intel Core i7-13800H, 1 CPU, 20 logical and 14 physical cores
.NET SDK 8.0.304
[Host] : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
```
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 |
Allocated | Alloc Ratio |
|----------
|---------:|--------:|--------:|------:|--------:|-------:|----------:|------------:|
| Baseline | 162.7 ns | 3.25 ns | 4.23 ns | 1.00 | 0.04 | 0.0088 |
112 B | 1.00 |
| Candidate | 152.8 ns | 1.38 ns | 1.22 ns | 0.94 | 0.02 | 0.0057 |
72 B | 0.64 |
Happy to check in some benchmarks for `DecimalUtility` if they might be
useful in future, but thought I'd leave them out for now.
If merged, will close #44237.
* GitHub Issue: #44237
Authored-by: George Vanburgh <[email protected]>
Signed-off-by: Curt Hagenlocher <[email protected]>
---
csharp/src/Apache.Arrow/DecimalUtility.cs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/csharp/src/Apache.Arrow/DecimalUtility.cs
b/csharp/src/Apache.Arrow/DecimalUtility.cs
index 1847b45a5c..363f816247 100644
--- a/csharp/src/Apache.Arrow/DecimalUtility.cs
+++ b/csharp/src/Apache.Arrow/DecimalUtility.cs
@@ -223,7 +223,14 @@ namespace Apache.Arrow
{
// create BigInteger from decimal
BigInteger bigInt;
+
+#if NET5_0_OR_GREATER
+ Span<int> decimalBits = stackalloc int[4];
+ decimal.GetBits(value, decimalBits);
+#else
int[] decimalBits = decimal.GetBits(value);
+#endif
+
int decScale = (decimalBits[3] >> 16) & 0x7F;
#if NETCOREAPP
Span<byte> bigIntBytes = stackalloc byte[13];