get the benchmark result, very POWERFULL
This commit is contained in:
@@ -11,6 +11,7 @@ StgSharp provides both low-level and high-level bindings to OpenGL, multimedia c
|
||||
## Core Modules
|
||||
|
||||
### StgSharp.Common
|
||||
|
||||
The main library containing core functionality:
|
||||
|
||||
- **Mathematics**: High-performance linear algebra, matrix operations, and mathematical utilities
|
||||
@@ -22,6 +23,7 @@ The main library containing core functionality:
|
||||
- **Environment**: Platform abstraction and system integration
|
||||
|
||||
### StgSharp.Script
|
||||
|
||||
General-purpose syntax analysis framework:
|
||||
|
||||
- **Syntax Analysis Framework**: Provides a flexible framework for parsing and analyzing various programming languages
|
||||
@@ -31,6 +33,7 @@ General-purpose syntax analysis framework:
|
||||
- **Grammar Parsing**: Extensible grammar parsing and validation system
|
||||
|
||||
### StgSharp.Model
|
||||
|
||||
Geometric model loading and interpretation:
|
||||
|
||||
- **Geometric Model Loading**: Responsible for loading and interpreting geometric models from various formats
|
||||
@@ -40,6 +43,7 @@ Geometric model loading and interpretation:
|
||||
- **Schema Validation**: Model structure validation and verification
|
||||
|
||||
### StgSharp.Native
|
||||
|
||||
Native library integration:
|
||||
|
||||
- **GLFW Integration**: Cross-platform window and input management
|
||||
@@ -48,6 +52,7 @@ Native library integration:
|
||||
- **Context Management**: Graphics context and resource management
|
||||
|
||||
### StgSharp.TerminalDialogue
|
||||
|
||||
Terminal-based user interface:
|
||||
|
||||
- **Interactive Terminal**: Command-line interface components
|
||||
@@ -57,34 +62,48 @@ Terminal-based user interface:
|
||||
## Key Features
|
||||
|
||||
### High-Performance Computing
|
||||
|
||||
- **Parallel Matrix Operations**: Multi-threaded matrix computations with optimized scheduling
|
||||
- **SIMD Acceleration**: Hardware-optimized vector operations
|
||||
- **Memory Management**: Custom allocators including HLSF (Hybrid Layer Segregated Fit)
|
||||
- **Thread Pool Management**: Efficient task scheduling and execution
|
||||
|
||||
#### HLSF Benchmark Snapshot (BenchmarkDotNet)
|
||||
Environment: Windows 11 (10.0.26100.7623), AMD Ryzen 7 6800H, .NET 8.0.23, x64 RyuJIT AVX2, GC = Concurrent Workstation.
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio |
|
||||
|------- |-----:|-----:|------:|------:|-------:|----------:|-----------:|
|
||||
| Hlsf | 838.4 µs | 16.67 µs | 40.58 µs | 1.00 | 0.12 | 64 B | 1.00 |
|
||||
| Libc | 849.8 µs | 34.93 µs | 100.23 µs | 1.01 | 0.17 | 64 B | 1.00 |
|
||||
```
|
||||
|
||||
This shows HLSF matching libc allocation throughput under the same workload. See the HLSF document for details and caveats.
|
||||
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.7623)
|
||||
AMD Ryzen 7 6800H with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
|
||||
.NET SDK 10.0.102
|
||||
[Host] : .NET 8.0.23 (8.0.2325.60607), X64 RyuJIT AVX2
|
||||
|
||||
Toolchain=InProcessEmitToolchain InvocationCount=2048 UnrollFactor=1
|
||||
|
||||
```
|
||||
|
||||
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|
||||
|------- |-----:|-----:|------:|------:|-------:|
|
||||
| Hlsf | 76.23 µs | 0.355 µs | 0.315 µs | 0.44 | 0.01 |
|
||||
| Libc | 172.98 µs | 3.042 µs | 2.988 µs | 1.00 | 0.02 |
|
||||
|
||||
This run shows HLSF significantly faster than libc under the current configuration. See the HLSF document for details and caveats.
|
||||
|
||||
### Graphics and Rendering
|
||||
|
||||
- **OpenGL Integration**: Complete OpenGL API coverage
|
||||
- **Cross-Platform Support**: Windows and Linux compatibility
|
||||
- **Rendering Pipeline**: Flexible and extensible graphics framework
|
||||
- **Shader Management**: Dynamic shader compilation and management
|
||||
|
||||
### Game Engine Capabilities
|
||||
|
||||
- **Entity System**: Flexible game object management
|
||||
- **State Machine**: Game state and behavior management
|
||||
- **Input Handling**: Comprehensive input and control systems
|
||||
- **Resource Management**: Efficient asset loading and management
|
||||
|
||||
### Data Processing
|
||||
|
||||
- **STEP File Support**: Industrial data format processing
|
||||
- **EXPRESS Language**: Domain-specific language compilation
|
||||
- **Pipeline Processing**: Efficient data transformation workflows
|
||||
|
||||
@@ -32,10 +32,12 @@ using System.Runtime.InteropServices;
|
||||
namespace StgSharp.Benchmark
|
||||
{
|
||||
[MemoryDiagnoser]
|
||||
[InvocationCount(16)]
|
||||
[InvocationCount(2048)]
|
||||
public class HlsfAllocatorBench
|
||||
{
|
||||
|
||||
private const uint Alignment = 64;
|
||||
|
||||
private const int AllocationCount = 2048;
|
||||
|
||||
private static readonly int[] AllocSizes = [
|
||||
@@ -55,7 +57,7 @@ namespace StgSharp.Benchmark
|
||||
[GlobalCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_hlsfAllocator.Dispose();
|
||||
_hlsfAllocator?.Dispose();
|
||||
_hlsfLocalList.Clear();
|
||||
_hlsfLocalList.TrimExcess();
|
||||
_libcLocalList.Clear();
|
||||
@@ -65,27 +67,7 @@ namespace StgSharp.Benchmark
|
||||
[Benchmark]
|
||||
public void Hlsf()
|
||||
{
|
||||
for (int i = 0; i < AllocationCount; i++)
|
||||
{
|
||||
lock (_hlsfAllocator)
|
||||
{
|
||||
HybridLayerSegregatedFitAllocationHandle allocate = _hlsfAllocator.Alloc(GetNextRandomSize());
|
||||
_hlsfLocalList.Add(allocate);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _hlsfLocalList.Count; i++)
|
||||
{
|
||||
lock (_hlsfAllocator) {
|
||||
_hlsfAllocator.Free(_hlsfLocalList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InvocationSetup()
|
||||
{
|
||||
_hlsfLocalList.Clear();
|
||||
_libcLocalList.Clear();
|
||||
RunHlsf(_hlsfAllocator, FreePolicy.NoCollect);
|
||||
}
|
||||
|
||||
[IterationSetup]
|
||||
@@ -98,9 +80,15 @@ namespace StgSharp.Benchmark
|
||||
[Benchmark(Baseline = true)]
|
||||
public unsafe void Libc()
|
||||
{
|
||||
_libcLocalList.Clear();
|
||||
|
||||
for (int i = 0; i < AllocationCount; i++)
|
||||
{
|
||||
void* allocate = NativeMemory.AlignedAlloc(GetNextRandomSize(), 64);
|
||||
uint size = AlignSize(GetNextRandomSize());
|
||||
void* allocate = NativeMemory.AlignedAlloc(size, Alignment);
|
||||
if (allocate == null) {
|
||||
throw new OutOfMemoryException("NativeMemory.AlignedAlloc returned null.");
|
||||
}
|
||||
_libcLocalList.Add((nint)allocate);
|
||||
}
|
||||
|
||||
@@ -113,7 +101,15 @@ namespace StgSharp.Benchmark
|
||||
public void Setup()
|
||||
{
|
||||
_random = new Random(42);
|
||||
_hlsfAllocator = new HybridLayerSegregatedFitAllocator(GetArenaBytes(), align:64);
|
||||
_hlsfAllocator = new HybridLayerSegregatedFitAllocator(GetArenaBytes(), align:(int)Alignment);
|
||||
}
|
||||
|
||||
private static uint AlignSize(
|
||||
uint size
|
||||
)
|
||||
{
|
||||
uint mask = Alignment - 1;
|
||||
return (size + mask) & ~mask;
|
||||
}
|
||||
|
||||
private static nuint GetArenaBytes()
|
||||
@@ -134,5 +130,24 @@ namespace StgSharp.Benchmark
|
||||
|
||||
private uint GetNextRandomSize() => (uint)AllocSizes[_random.Next(AllocSizes.Length)];
|
||||
|
||||
private void RunHlsf(
|
||||
HybridLayerSegregatedFitAllocator allocator,
|
||||
FreePolicy policy
|
||||
)
|
||||
{
|
||||
_hlsfLocalList.Clear();
|
||||
|
||||
for (int i = 0; i < AllocationCount; i++)
|
||||
{
|
||||
uint size = AlignSize(GetNextRandomSize());
|
||||
HybridLayerSegregatedFitAllocationHandle allocate = allocator.Alloc(size);
|
||||
_hlsfLocalList.Add(allocate);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _hlsfLocalList.Count; i++) {
|
||||
allocator.Free(_hlsfLocalList[i], policy);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||
using StgSharp.Benchmark;
|
||||
|
||||
namespace StgSharp.Benchmark
|
||||
@@ -37,7 +41,10 @@ namespace StgSharp.Benchmark
|
||||
string[] args
|
||||
)
|
||||
{
|
||||
BenchmarkRunner.Run<HlsfAllocatorBench>();
|
||||
IConfig config = ManualConfig.Create(DefaultConfig.Instance)
|
||||
.AddLogger(ConsoleLogger.Default)
|
||||
.AddJob(Job.Default.WithToolchain(InProcessEmitToolchain.Instance));
|
||||
BenchmarkRunner.Run<HlsfAllocatorBench>(config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,15 @@ using hlsfHandle = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAlloc
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public enum FreePolicy
|
||||
{
|
||||
|
||||
FullCollect,
|
||||
LazyCollect,
|
||||
NoCollect
|
||||
|
||||
}
|
||||
|
||||
public unsafe partial class HybridLayerSegregatedFitAllocator
|
||||
{
|
||||
|
||||
@@ -79,9 +88,11 @@ namespace StgSharp.HighPerformance.Memory
|
||||
/// </summary>
|
||||
/// <param name="handle">
|
||||
/// Handle to the allocated memory block
|
||||
/// <param name="collectPolicy">
|
||||
/// </param>
|
||||
public void Free(
|
||||
hlsfHandle handle
|
||||
hlsfHandle handle,
|
||||
FreePolicy collectPolicy = FreePolicy.NoCollect
|
||||
)
|
||||
{
|
||||
Entry* e = handle.EntryHandle;
|
||||
@@ -96,7 +107,10 @@ namespace StgSharp.HighPerformance.Memory
|
||||
e->State = EntryState.Empty;
|
||||
|
||||
// Try merge with adjacent free blocks and remove them from buckets
|
||||
if (collectPolicy == FreePolicy.LazyCollect)
|
||||
{
|
||||
MergeAndRemoveFromBuckets(e);
|
||||
}
|
||||
|
||||
// Calculate final level and segment for the merged block
|
||||
long finalSize = e->Size;
|
||||
@@ -108,6 +122,10 @@ namespace StgSharp.HighPerformance.Memory
|
||||
PushBucketToLevel(finalLevel, finalSegment, (BucketNode*)e->Position);
|
||||
|
||||
// Console.WriteLine("one block freed");
|
||||
if (collectPolicy == FreePolicy.FullCollect)
|
||||
{
|
||||
Collect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
uint maxBlockSize
|
||||
)
|
||||
{
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked);
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked, false);
|
||||
m_Buffer = (byte *)NativeMemory.AlignedAlloc(byteSize, (nuint)16);
|
||||
_align = 16;
|
||||
_size = byteSize;
|
||||
@@ -111,7 +111,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
throw new ArgumentException(
|
||||
"Alignment must be a power of two and at least 16 bytes.");
|
||||
}
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked);
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked, false);
|
||||
m_Buffer = (byte *)NativeMemory.AlignedAlloc(byteSize, (nuint)align);
|
||||
_align = align;
|
||||
_size = byteSize;
|
||||
@@ -138,7 +138,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
throw new ArgumentException(
|
||||
"Alignment must be a power of two and at least 16 bytes.");
|
||||
}
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked);
|
||||
_entries = SlabAllocator<Entry>.Create(64, SlabBufferLayout.Chunked, false);
|
||||
m_Buffer = (byte *)NativeMemory.AlignedAlloc(byteSize, (nuint)align);
|
||||
_align = align;
|
||||
_size = byteSize;
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
internal sealed unsafe class ChunkedSlabAllocator<T> : SlabAllocator<T> where T : unmanaged
|
||||
{
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private BufferStack<nuint> _buffers;
|
||||
private BufferStack<nuint> _recycle;
|
||||
private readonly int _elementSize = Unsafe.SizeOf<T>();
|
||||
@@ -90,6 +92,10 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_disposed) {
|
||||
return;
|
||||
}
|
||||
_disposed = true;
|
||||
// NativeMemory.Free((void*)_currentBuffer);
|
||||
while (_buffers.TryPop(out nuint buffer))
|
||||
{
|
||||
@@ -97,6 +103,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
}
|
||||
_buffers.Dispose();
|
||||
_recycle.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
internal sealed unsafe class ConcurrentChunkedSlabAllocator<T> : SlabAllocator<T> where T : unmanaged
|
||||
{
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private ConcurrentBufferStack<nuint> _buffers;
|
||||
private ConcurrentBufferStack<nuint> _recycle;
|
||||
@@ -114,6 +116,10 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_disposed) {
|
||||
return;
|
||||
}
|
||||
_disposed = true;
|
||||
NativeMemory.Free((void*)_currentBuffer);
|
||||
while (_buffers.TryPop(out nuint buffer)) {
|
||||
NativeMemory.Free((void*)buffer);
|
||||
@@ -121,6 +127,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
_lock.Dispose();
|
||||
_buffers.Dispose();
|
||||
_recycle.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
public sealed unsafe class ConcurrentSequentialSlabAllocator<T> : SlabAllocator<T> where T: unmanaged
|
||||
{
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
private T* _buffer;
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
@@ -120,9 +122,14 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_disposed) {
|
||||
return;
|
||||
}
|
||||
_disposed = true;
|
||||
_stack.Dispose();
|
||||
NativeMemory.Free(_buffer);
|
||||
_lock.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@@ -51,10 +51,10 @@ DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, sse, , fma)
|
||||
c3 = _mm_add_ps(c3, _mm_mul_ps(a2, _mm_shuffle_ps(bcol, bcol, _FMA_SELECT(2))));
|
||||
c3 = _mm_add_ps(c3, _mm_mul_ps(a3, _mm_shuffle_ps(bcol, bcol, _FMA_SELECT(3))));
|
||||
|
||||
ans->f32_x[0] = c0;
|
||||
ans->f32_x[1] = c1;
|
||||
ans->f32_x[2] = c2;
|
||||
ans->f32_x[3] = c3;
|
||||
_mm_store_ps((float *)&ans->f32_x[0], c0);
|
||||
_mm_store_ps((float *)&ans->f32_x[1], c1);
|
||||
_mm_store_ps((float *)&ans->f32_x[2], c2);
|
||||
_mm_store_ps((float *)&ans->f32_x[3], c3);
|
||||
}
|
||||
|
||||
DECLARE_KER_PROC_LEFT_RIGHT_ANS(float, avx, , fma)
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace StgSharp
|
||||
.UseModule<NumericalModule>()
|
||||
.UseModule<GraphicModule>()
|
||||
.InitializeModule();
|
||||
TestMatrix();
|
||||
|
||||
HlsfStressTest.Run();
|
||||
|
||||
// TestMatrix();
|
||||
|
||||
|
||||
// --- Logarithmic time sequence test: print seconds at each emitted span ---
|
||||
|
||||
Reference in New Issue
Block a user