aboutsummaryrefslogtreecommitdiff
path: root/lib/Utils
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-05-10 21:57:31 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-05-10 21:57:31 -0400
commit5e1f4cf3f8bcc64114478e1547822a2f5295f6ae (patch)
tree7fe77901db253cc7bc5e992a2ba400072ad66fe2 /lib/Utils
parent067c692800970e6fc41fbd0df669a6b1d6a07c55 (diff)
Yuge http buffering overhaul
Diffstat (limited to 'lib/Utils')
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs32
-rw-r--r--lib/Utils/src/Memory/VnString.cs28
2 files changed, 48 insertions, 12 deletions
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index 1be46e4..c4cbc2f 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -82,6 +82,7 @@ namespace VNLib.Utils.Memory
/// </summary>
public const int MAX_UNSAFE_POOL_SIZE = 80 * 1024;
+ //Cache the system page size
private static readonly int SystemPageSize = Environment.SystemPageSize;
/// <summary>
@@ -266,6 +267,12 @@ namespace VNLib.Utils.Memory
}
}
+ /*
+ * Initializing a non-readonly span/memory as of .NET 6.0 is a reference
+ * reintpretation, essentially a pointer cast, so there is little/no cost
+ * to implicitely casting to a readonly span/memory types to reduce complexity
+ */
+
/// <summary>
/// Initializes a block of memory with zeros
/// </summary>
@@ -297,7 +304,7 @@ namespace VNLib.Utils.Memory
}
//Get the size of the structure
- int size = Unsafe.SizeOf<T>();
+ int size = sizeof(T);
//Zero block
Unsafe.InitBlock(block, 0, (uint)(size * itemCount));
@@ -310,7 +317,7 @@ namespace VNLib.Utils.Memory
/// <param name="block">The pointer to the allocated structure</param>
public static void ZeroStruct<T>(IntPtr block)
{
- //get thes size of the structure
+ //get thes size of the structure does not have to be primitive type
int size = Unsafe.SizeOf<T>();
//Zero block
Unsafe.InitBlock(block.ToPointer(), 0, (uint)size);
@@ -321,7 +328,7 @@ namespace VNLib.Utils.Memory
/// </summary>
/// <typeparam name="T">The structure type</typeparam>
/// <param name="structPtr">The pointer to the allocated structure</param>
- public static void ZeroStruct<T>(void* structPtr) where T: unmanaged
+ public static void ZeroStruct<T>(void* structPtr)
{
//get thes size of the structure
int size = Unsafe.SizeOf<T>();
@@ -336,10 +343,8 @@ namespace VNLib.Utils.Memory
/// <param name="structPtr">The pointer to the allocated structure</param>
public static void ZeroStruct<T>(T* structPtr) where T : unmanaged
{
- //get thes size of the structure
- int size = Unsafe.SizeOf<T>();
//Zero block
- Unsafe.InitBlock(structPtr, 0, (uint)size);
+ Unsafe.InitBlock(structPtr, 0, (uint)sizeof(T));
}
#endregion
@@ -669,8 +674,10 @@ namespace VNLib.Utils.Memory
//Pin the array
GCHandle arrHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
+
//Get array base address
void* basePtr = (void*)arrHandle.AddrOfPinnedObject();
+
//Get element offset
void* indexOffet = Unsafe.Add<T>(basePtr, elementOffset);
@@ -678,6 +685,19 @@ namespace VNLib.Utils.Memory
}
/// <summary>
+ /// Gets a runtime <see cref="MemoryHandle"/> wrapper for the given pointer
+ /// </summary>
+ /// <param name="value">The pointer to get the handle for</param>
+ /// <param name="handle">The optional <see cref="GCHandle"/> to attach</param>
+ /// <param name="pinnable">An optional <see cref="IPinnable"/> instace to wrap with the handle</param>
+ /// <returns>The <see cref="MemoryHandle"/> wrapper</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static MemoryHandle GetMemoryHandleFromPointer(IntPtr value, GCHandle handle = default, IPinnable? pinnable = null)
+ {
+ return new MemoryHandle(value.ToPointer(), handle, pinnable);
+ }
+
+ /// <summary>
/// Gets a <see cref="Span{T}"/> from the supplied address
/// </summary>
/// <typeparam name="T"></typeparam>
diff --git a/lib/Utils/src/Memory/VnString.cs b/lib/Utils/src/Memory/VnString.cs
index 8bb0bb6..7df6009 100644
--- a/lib/Utils/src/Memory/VnString.cs
+++ b/lib/Utils/src/Memory/VnString.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -239,13 +239,16 @@ namespace VNLib.Utils.Memory
{
throw new IOException("The input stream is not readable");
}
+
//See if the stream is a vn memory stream
if (stream is VnMemoryStream vnms)
{
//Get the number of characters
int numChars = encoding.GetCharCount(vnms.AsSpan());
+
//New handle
MemoryHandle<char> charBuffer = heap.Alloc<char>(numChars);
+
try
{
//Write characters to character buffer
@@ -264,8 +267,10 @@ namespace VNLib.Utils.Memory
{
//Create a new char bufer starting with the buffer size
MemoryHandle<char> charBuffer = heap.Alloc<char>(bufferSize);
+
//Rent a temp binary buffer
IMemoryOwner<byte> binBuffer = heap.DirectAlloc<byte>(bufferSize);
+
try
{
int length = 0;
@@ -273,22 +278,28 @@ namespace VNLib.Utils.Memory
{
//read async
int read = await stream.ReadAsync(binBuffer.Memory);
+
//guard
if (read <= 0)
{
break;
}
+
//calculate the number of characters
int numChars = encoding.GetCharCount(binBuffer.Memory.Span[..read]);
+
//Guard for overflow
if (((ulong)(numChars + length)) >= int.MaxValue)
{
throw new OverflowException();
}
+
//Re-alloc buffer
charBuffer.ResizeIfSmaller(length + numChars);
+
//Decode and update position
_ = encoding.GetChars(binBuffer.Memory.Span[..read], charBuffer.Span.Slice(length, numChars));
+
//Update char count
length += numChars;
} while (true);
@@ -319,6 +330,7 @@ namespace VNLib.Utils.Memory
{
//Check
Check();
+
//Check bounds
return _stringSequence.Span[index];
}
@@ -341,13 +353,16 @@ namespace VNLib.Utils.Memory
{
//Check
Check();
+
//Check bounds
if (start < 0 || (start + count) >= Length)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
+
//get sub-sequence slice for the current string
SubSequence<char> sub = _stringSequence.Slice((nuint)start, count);
+
//Create new string with offsets pointing to same internal referrence
return new VnString(sub);
}
@@ -365,6 +380,7 @@ namespace VNLib.Utils.Memory
/// <exception cref="ObjectDisposedException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public VnString Substring(int start) => Substring(start, (Length - start));
+
public VnString this[Range range]
{
get
@@ -489,16 +505,16 @@ namespace VNLib.Utils.Memory
Handle?.Dispose();
}
- public static bool operator ==(VnString left, VnString right) => ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.Equals(right);
+ public static bool operator ==(VnString left, VnString right) => left is null ? right is not null : left.Equals(right, StringComparison.Ordinal);
public static bool operator !=(VnString left, VnString right) => !(left == right);
- public static bool operator <(VnString left, VnString right) => ReferenceEquals(left, null) ? !ReferenceEquals(right, null) : left.CompareTo(right) < 0;
+ public static bool operator <(VnString left, VnString right) => left is null ? right is not null : left.CompareTo(right) < 0;
- public static bool operator <=(VnString left, VnString right) => ReferenceEquals(left, null) || left.CompareTo(right) <= 0;
+ public static bool operator <=(VnString left, VnString right) => left is null || left.CompareTo(right) <= 0;
- public static bool operator >(VnString left, VnString right) => !ReferenceEquals(left, null) && left.CompareTo(right) > 0;
+ public static bool operator >(VnString left, VnString right) => left is not null && left.CompareTo(right) > 0;
- public static bool operator >=(VnString left, VnString right) => ReferenceEquals(left, null) ? ReferenceEquals(right, null) : left.CompareTo(right) >= 0;
+ public static bool operator >=(VnString left, VnString right) => left is null ? right is null : left.CompareTo(right) >= 0;
}
} \ No newline at end of file