Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/antiufo/roslyn-linq-rewrite
Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch.
https://github.com/antiufo/roslyn-linq-rewrite
Last synced: 3 months ago
JSON representation
Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch.
- Host: GitHub
- URL: https://github.com/antiufo/roslyn-linq-rewrite
- Owner: antiufo
- License: mit
- Created: 2016-09-09T13:07:03.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2020-02-02T08:47:28.000Z (almost 5 years ago)
- Last Synced: 2024-07-31T21:53:21.429Z (5 months ago)
- Language: C#
- Homepage:
- Size: 324 KB
- Stars: 717
- Watchers: 41
- Forks: 31
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
- awesome-csharp - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
- awesome-dotnet-cn - Roslyn-linq-rewrite - 通过先重写LINQ表达式的语法树,以便使用简单的程序码编译C#代码,做到配置与动态分配最小化。 (编译器、透明机和语言)
- awesome-dotnet - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
- awesome-dotnet - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
- awesome-dot-dev - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
- awsome-dotnet - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
- awesome-roslyn - roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code. This increases performance by minimizes heap allocations and dynamic dispatch. (Open Source Projects)
- awesome-dotnet - Roslyn-linq-rewrite - Compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch. (Compilers, Transpilers and Languages)
README
# roslyn-linq-rewrite
This tool compiles C# code by first rewriting the syntax trees of LINQ expressions using plain procedural code, minimizing allocations and dynamic dispatch.## Example input code
```csharp
public int Method1()
{
var arr = new[] { 1, 2, 3, 4 };
var q = 2;
return arr.Where(x => x > q).Select(x => x + 3).Sum();
}
```
**Allocations**: input array, array enumerator, closure for `q`, `Where` delegate, `Select` delegate, `Where` enumerator, `Select` enumerator.
## Decompiled output code
```csharp
public int Method1()
{
int[] arr = new[] { 1, 2, 3, 4 };
int q = 2;
return this.Method1_ProceduralLinq1(arr, q);
}
private int Method1_ProceduralLinq1(int[] _linqitems, int q)
{
if (_linqitems == null) throw new ArgumentNullException();int num = 0;
for (int i = 0; i < _linqitems.Length; i++)
{
int num2 = _linqitems[i];
if (num2 > q)
num += num2 + 3;
}
return num;
}
```
**Allocations**: input array.*Note: in this example, the optimizing compiler has generated code using arrays, because the type was known at compile time. When this is not the case, the generated code will instead use a `foreach` and `IEnumerable<>`.*
*Non-optimizable call chains and `IQueryable<>` are left intact.*
## Supported LINQ methods
* `Select`, `Where`, `Reverse`, `Cast`, `OfType`
* `First`, `FirstOrDefault`, `Single`, `SingleOrDefault`, `Last`, `LastOrDefault`
* `ToList`, `ToArray`, `ToDictionary`
* `Count`, `LongCount`, `Any`, `All`
* `ElementAt`, `ElementAtOrDefault`
* `Contains`, `ForEach`## Usage (.sln/.csproj)
* Download the [latest binaries](https://github.com/antiufo/roslyn-linq-rewrite/releases)
* `roslyn-linq-rewrite [--release]`Note: you can more deeply integrate the optimizing compiler with MSBuild by setting `CscToolPath` to the roslyn-linq-rewrite directory.
## Usage (project.json)
* Add the following to your `project.json`:
```json
"tools": {
"dotnet-compile-csc-linq-rewrite": {
"version": "1.0.1.9",
"imports": "portable-net45+win8+wp8+wpa81"
}
}
```
* In the `buildOptions` of your `project.json`, specify the custom compiler:
```json
"buildOptions": {
"compilerName": "csc-linq-rewrite"
}
```
* Compile your project with `dotnet restore` and `dotnet build`.
* If you need to exclude a specific method, apply a `[NoLinqRewrite]` attribute to that method:
```csharp
namespace Shaman.Runtime
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method)]
public class NoLinqRewriteAttribute : Attribute
{
}
}
```## Tests
Here's a [diff](https://github.com/antiufo/linqtests/blob/master/tests/Shaman.Roslyn.LinqRewrite.Tests/Results_diff.diff) (and its [code](https://github.com/antiufo/linqtests/blob/master/tests/Shaman.Roslyn.LinqRewrite.Tests/)) between the ordinary LINQ tests and the version compiled with roslyn-linq-rewrite. The only difference seems to be related about a `Min`/`Max` with `NaN` values, I'm planning to fix it soon.## Shaman.FastLinq
To further reduce allocations, install `Shaman.FastLinq` or `Shaman.FastLinq.Sources`. These packages include LINQ methods specific for `T[]` and `List<>` (not all method calls are optimized by LINQ rewrite, like individual, non-chained `.First()` or `.Last()` calls).## Comparison to LinqOptimizer
* Code is optimized at build time (as opposed to run time)
* Uses existing LINQ syntax, no need for `AsQueryExpr().Run()`
* No allocations for `Expression<>` trees and enumerator boxing
* Parallel LINQ is not supported (i.e. left intact)
* No support for F#