Skip to content

Commit c83fafa

Browse files
committed
Save memory allocations when reading Guid or BitString
1 parent 9fce699 commit c83fafa

File tree

3 files changed

+51
-37
lines changed

3 files changed

+51
-37
lines changed

DuckDB.NET.Data/Data.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Added support for writing to List and Array columns when using managed Appender.
2222
</ItemGroup>
2323
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
2424
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
25+
<PackageReference Include="System.Memory" Version="4.5.5" />
2526
</ItemGroup>
2627
<ItemGroup>
2728
<ProjectReference Include="..\DuckDB.NET.Bindings\Bindings.csproj" />

DuckDB.NET.Data/Extensions/GuidConverter.cs

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,59 @@ namespace DuckDB.NET.Data.Extensions;
66

77
internal static class GuidConverter
88
{
9+
private const string GuidFormat = "D";
910
private static readonly char[] HexDigits = "0123456789abcdef".ToCharArray();
1011

1112
//Ported from duckdb source code UUID::ToString
1213
//https://github.com/duckdb/duckdb/blob/9c91b3a329073ea1767b0aaff94b51da98dd03e2/src/common/types/uuid.cpp#L56
1314
public static Guid ConvertToGuid(this DuckDBHugeInt input)
1415
{
15-
var buffer = new char[36];
16-
17-
var upper = input.Upper ^ (((long)1) << 63);
16+
Span<char> buffer = stackalloc char[36];
17+
var num = input.Upper ^ long.MinValue;
1818
var position = 0;
19-
20-
ByteToHex((ulong)(upper >> 56 & 0xFF));
21-
ByteToHex((ulong)(upper >> 48 & 0xFF));
22-
ByteToHex((ulong)(upper >> 40 & 0xFF));
23-
ByteToHex((ulong)(upper >> 32 & 0xFF));
24-
19+
20+
ByteToHex(buffer, ref position, (ulong)((num >> 56) & 0xFF));
21+
ByteToHex(buffer, ref position, (ulong)((num >> 48) & 0xFF));
22+
ByteToHex(buffer, ref position, (ulong)((num >> 40) & 0xFF));
23+
ByteToHex(buffer, ref position, (ulong)((num >> 32) & 0xFF));
24+
2525
buffer[position++] = '-';
26-
27-
ByteToHex((ulong)(upper >> 24 & 0xFF));
28-
ByteToHex((ulong)(upper >> 16 & 0xFF));
29-
26+
27+
ByteToHex(buffer, ref position, (ulong)((num >> 24) & 0xFF));
28+
ByteToHex(buffer, ref position, (ulong)((num >> 16) & 0xFF));
29+
3030
buffer[position++] = '-';
31-
32-
ByteToHex((ulong)(upper >> 8 & 0xFF));
33-
ByteToHex((ulong)(upper & 0xFF));
34-
31+
32+
ByteToHex(buffer, ref position, (ulong)((num >> 8) & 0xFF));
33+
ByteToHex(buffer, ref position, (ulong)(num & 0xFF));
34+
3535
buffer[position++] = '-';
36-
37-
ByteToHex(input.Lower >> 56 & 0xFF);
38-
ByteToHex(input.Lower >> 48 & 0xFF);
39-
36+
37+
ByteToHex(buffer, ref position, (input.Lower >> 56) & 0xFF);
38+
ByteToHex(buffer, ref position, (input.Lower >> 48) & 0xFF);
39+
4040
buffer[position++] = '-';
41-
42-
ByteToHex(input.Lower >> 40 & 0xFF);
43-
ByteToHex(input.Lower >> 32 & 0xFF);
44-
ByteToHex(input.Lower >> 24 & 0xFF);
45-
ByteToHex(input.Lower >> 16 & 0xFF);
46-
ByteToHex(input.Lower >> 8 & 0xFF);
47-
ByteToHex(input.Lower & 0xFF);
48-
49-
return new Guid(new string(buffer));
50-
51-
void ByteToHex(ulong value)
41+
42+
ByteToHex(buffer, ref position, (input.Lower >> 40) & 0xFF);
43+
ByteToHex(buffer, ref position, (input.Lower >> 32) & 0xFF);
44+
ByteToHex(buffer, ref position, (input.Lower >> 24) & 0xFF);
45+
ByteToHex(buffer, ref position, (input.Lower >> 16) & 0xFF);
46+
ByteToHex(buffer, ref position, (input.Lower >> 8) & 0xFF);
47+
ByteToHex(buffer, ref position, input.Lower & 0xFF);
48+
49+
#if NET6_0_OR_GREATER
50+
return Guid.ParseExact(buffer, GuidFormat);
51+
#else
52+
return Guid.ParseExact(new string(buffer.ToArray()), GuidFormat);
53+
#endif
54+
55+
static void ByteToHex(Span<char> buffer, ref int position, ulong value)
5256
{
53-
buffer[position++] = HexDigits[(value >> 4) & 0xf];
54-
buffer[position++] = HexDigits[value & 0xf];
57+
buffer[position++] = HexDigits[(value >> 4) & 0xF];
58+
buffer[position++] = HexDigits[value & 0xF];
5559
}
5660
}
5761

58-
5962
//https://github.com/duckdb/duckdb/blob/9c91b3a329073ea1767b0aaff94b51da98dd03e2/src/common/types/uuid.cpp#L6
6063
public static DuckDBHugeInt ToHugeInt(this Guid guid)
6164
{

DuckDB.NET.Data/Internal/Reader/StringVectorDataReader.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
using System;
1+
using DuckDB.NET.Native;
2+
using System;
23
using System.Collections;
34
using System.IO;
45
using System.Text;
5-
using DuckDB.NET.Native;
66

77
namespace DuckDB.NET.Data.Internal.Reader;
88

@@ -53,6 +53,15 @@ private string GetBitString(ulong offset)
5353
{
5454
var bitArray = GetBitStringAsBitArray(offset);
5555

56+
#if NET6_0_OR_GREATER
57+
return string.Create(bitArray.Length, bitArray, (chars, array) =>
58+
{
59+
for (int index = 0; index < array.Length; index++)
60+
{
61+
chars[index] = array[index] ? '1' : '0';
62+
}
63+
});
64+
#else
5665
var output = new char[bitArray.Length];
5766

5867
for (var index = 0; index < bitArray.Count; index++)
@@ -61,6 +70,7 @@ private string GetBitString(ulong offset)
6170
}
6271

6372
return new string(output);
73+
#endif
6474
}
6575

6676
//Copied from https://github.com/duckdb/duckdb/blob/8a17511028d306561d88da9425f9e0e88dedd70c/src/common/types/bit.cpp#L63

0 commit comments

Comments
 (0)