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];

Reply via email to