Home

Awesome

StructLinq

GitHub release
Nuget Nuget
Build Status continuous
GitHub stars GitHub forks License

Implementation in C# of LINQ concept with struct to reduce drastically memory allocation and improve performance. Introduce IRefStructEnumerable to improve performance when element are fat struct.



Installation

This library is distributed via NuGet. To install StructLinq :

PM> Install-Package StructLinq

Usage

StructLinq use massively generic concept and struct "specialization".

using StructLinq;
 
int[] array = new [] {1, 2, 3, 4, 5};

int result = array
                .ToStructEnumerable()
                .Where(x => (x & 1) == 0, x=>x)
                .Select(x => x *2, x => x)
                .Sum();

x=>x is used to avoid boxing (and allocation) and to help generic type parameters inference. You can also improve performance by using struct for Where predicate and select function.

Performances

All benchmark results are in here. For example following linq sequence:

   list
     .Where(x => (x & 1) == 0)
     .Select(x => x * 2)
     .Sum();

can be replace by:

  list
    .ToStructEnumerable()
    .Where(x => (x & 1) == 0)
    .Select(x => x * 2)
    .Sum();

or if you want zero allocation by:

 list
   .ToStructEnumerable()
   .Where(x => (x & 1) == 0, x=>x)
   .Select(x => x * 2, x=>x)
   .Sum(x=>x);

or if you want zero allocation and better performance by:

  var where = new WherePredicate();
  var select = new SelectFunction();
  list
    .ToStructEnumerable()
    .Where(ref @where, x => x)
    .Select(ref @select, x => x, x => x)
    .Sum(x => x);

Benchmark results are:


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=5.0.101
  [Host]     : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT
  DefaultJob : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT


MethodMeanErrorStdDevRatioGen 0Gen 1Gen 2Allocated
LINQ65.116 μs0.6153 μs0.5756 μs1.00---152 B
StructLinqWithDelegate26.146 μs0.2402 μs0.2247 μs0.40---96 B
StructLinqWithDelegateZeroAlloc27.854 μs0.0938 μs0.0783 μs0.43----
StructLinqZeroAlloc6.872 μs0.0155 μs0.0137 μs0.11----

StructLinq is significatively faster than default LINQ implementation.

Features

Duck typing with foreach is available with zero allocation for IStructEnumerable.

BCL

Following class have a StructLinq extension method for IStructEnumerable:

Converters

Following converters are available for :

LINQ Extensions

Following extensions are available for :

Other Extensions

IRefStructEnumerable

    public interface IRefStructEnumerable<out T, out TEnumerator>
        where TEnumerator : struct, IRefStructEnumerator<T>
    {
        TEnumerator GetEnumerator();
    }

    public interface IRefStructEnumerator<T>
    {
        bool MoveNext();

        void Reset();

        ref T Current { get; }
    }

ref Current allows to avoid copy. I should be very useful when T is a fat struct.

Duck typing with foreach with ref is available with zero allocation for IRefStructEnumerable.

BCL

Following class have a StructLinq extension method for IRefStructEnumerable:

Converters

Following converters are available for :

LINQ Extensions

Following extensions are available for :

Other Extensions