Add image processing and memory management features

Added new namespace `Misaki.HighPerformance.Image` for image processing, including classes for animated GIF handling and memory management.
Added `AnimatedFrameResult` class for individual frames in animated images.
Added `AnimatedGifEnumerator` class for enumerating frames in animated GIFs.
Added `ColorComponents` enum for different color formats.
Added `ImageInfo` struct for image dimensions and color components.
Added `CRuntime` class for low-level memory management functions.
Added `MemoryStats` class to track memory allocation statistics.
Added utility functions for creating multi-dimensional arrays.
Added new structures for fixed-size UTF-8 encoded strings.
Added benchmarking classes to test new memory management features.

Changed `StbImage.cs` to include new namespaces and functionality for image data manipulation.
Changed project files to target .NET 9.0 and enable new features.
Changed `Arena.cs` and `DynamicArena.cs` to use `nuint` for size parameters.
Changed `BitSet.cs` to enhance bit manipulation methods.
Changed `Program.cs` to run `FunctionPtrBenchmark` for performance testing.

Removed memory tracking code from `AllocationManager.cs`, including the `_allocated` dictionary and related logic.
Removed `Free` method from `IAllocator.cs` interface.
Removed `UNSAFE_COLLECTION_CHECK` preprocessor directive from the codebase.

Refactored various files to improve organization, moving from `Unsafe` to `LowLevel` namespace.
Refactored `MemoryUtilities` class to include new memory operation methods.
Refactored `UnsafeUtilities.cs` to support new collection structures.
This commit is contained in:
2025-07-12 19:48:42 +09:00
parent d306f183de
commit eeff3313b5
72 changed files with 14444 additions and 471 deletions

View File

@@ -0,0 +1,186 @@
using System;
using System.Runtime.InteropServices;
namespace Misaki.HighPerformance.Image.Runtime
{
internal static unsafe class CRuntime
{
private static readonly string numbers = "0123456789";
public static void* malloc(ulong size)
{
return malloc((long)size);
}
public static void* malloc(long size)
{
var ptr = NativeMemory.Alloc((nuint)size);
MemoryStats.Allocated();
return ptr;
}
public static void free(void* ptr)
{
if (ptr == null)
return;
NativeMemory.Free(ptr);
MemoryStats.Freed();
}
public static void memcpy(void* a, void* b, long size)
{
NativeMemory.Copy(b, a, (nuint)size);
}
public static void memcpy(void* a, void* b, ulong size)
{
memcpy(a, b, (long)size);
}
public static void memmove(void* a, void* b, long size)
{
void* temp = null;
try
{
temp = malloc(size);
memcpy(temp, b, size);
memcpy(a, temp, size);
}
finally
{
if (temp != null)
free(temp);
}
}
public static int memcmp(void* a, void* b, long size)
{
var result = 0;
var ap = (byte*)a;
var bp = (byte*)b;
for (long i = 0; i < size; ++i)
{
if (*ap != *bp)
result += 1;
ap++;
bp++;
}
return result;
}
public static void memset(void* ptr, int value, long size)
{
NativeMemory.Fill(ptr, (nuint)size, (byte)value);
}
public static void memset(void* ptr, int value, ulong size)
{
memset(ptr, value, (long)size);
}
public static uint _lrotl(uint x, int y)
{
return x << y | x >> 32 - y;
}
public static void* realloc(void* ptr, long newSize)
{
if (ptr == null)
return malloc(newSize);
var result = NativeMemory.Realloc(ptr, (nuint)newSize);
return result;
}
public static void* realloc(void* a, ulong newSize)
{
return realloc(a, (long)newSize);
}
public static int abs(int v)
{
return Math.Abs(v);
}
public static double pow(double a, double b)
{
return Math.Pow(a, b);
}
public static double ldexp(double number, int exponent)
{
return number * Math.Pow(2, exponent);
}
public static int strcmp(sbyte* src, string token)
{
var result = 0;
for (var i = 0; i < token.Length; ++i)
{
if (src[i] != token[i])
{
++result;
}
}
return result;
}
public static int strncmp(sbyte* src, string token, ulong size)
{
var result = 0;
for (var i = 0; i < Math.Min(token.Length, (int)size); ++i)
{
if (src[i] != token[i])
{
++result;
}
}
return result;
}
public static long strtol(sbyte* start, sbyte** end, int radix)
{
// First step - determine length
var length = 0;
var ptr = start;
while (numbers.IndexOf((char)*ptr) != -1)
{
++ptr;
++length;
}
long result = 0;
// Now build up the number
ptr = start;
while (length > 0)
{
long num = numbers.IndexOf((char)*ptr);
var pow = (long)Math.Pow(10, length - 1);
result += num * pow;
++ptr;
--length;
}
if (end != null)
{
*end = ptr;
}
return result;
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Threading;
namespace Misaki.HighPerformance.Image.Runtime
{
internal unsafe static class MemoryStats
{
private static int _allocations;
public static int Allocations
{
get
{
return _allocations;
}
}
internal static void Allocated()
{
Interlocked.Increment(ref _allocations);
}
internal static void Freed()
{
Interlocked.Decrement(ref _allocations);
}
}
}

View File

@@ -0,0 +1,16 @@
namespace Misaki.HighPerformance.Image.Runtime
{
internal class Utility
{
public static T[][] CreateArray<T>(int d1, int d2)
{
var result = new T[d1][];
for (var i = 0; i < d1; i++)
{
result[i] = new T[d2];
}
return result;
}
}
}