![]() |
VOOZH | about |
dotnet add package Gapotchenko.FX.Runtime.CompilerServices.Intrinsics --version 2026.7.2
NuGet\Install-Package Gapotchenko.FX.Runtime.CompilerServices.Intrinsics -Version 2026.7.2
<PackageReference Include="Gapotchenko.FX.Runtime.CompilerServices.Intrinsics" Version="2026.7.2" />
<PackageVersion Include="Gapotchenko.FX.Runtime.CompilerServices.Intrinsics" Version="2026.7.2" />Directory.Packages.props
<PackageReference Include="Gapotchenko.FX.Runtime.CompilerServices.Intrinsics" />Project file
paket add Gapotchenko.FX.Runtime.CompilerServices.Intrinsics --version 2026.7.2
#r "nuget: Gapotchenko.FX.Runtime.CompilerServices.Intrinsics, 2026.7.2"
#:package Gapotchenko.FX.Runtime.CompilerServices.Intrinsics@2026.7.2
#addin nuget:?package=Gapotchenko.FX.Runtime.CompilerServices.Intrinsics&version=2026.7.2Install as a Cake Addin
#tool nuget:?package=Gapotchenko.FX.Runtime.CompilerServices.Intrinsics&version=2026.7.2Install as a Cake Tool
The module allows to define and compile intrinsic functions using machine code. They can be used in hardware-accelerated implementations of performance-sensitive algorithms.
Suppose we are trying to fix the performance bottleneck in the following algorithm:
class BitOperations
{
// Returns the base 2 logarithm of a specified number.
public static int Log2_Trivial(uint value)
{
int r = 0;
while ((value >>= 1) != 0)
++r;
return r;
}
}
log<sub>2</sub> seems to be a trivial operation but it often becomes a serious bottleneck in path-finding or cryptographic algorithms. We can do better here if we switch to a table lookup:
class BitOperations
{
// "Bit Twiddling Hacks" by Sean Eron Anderson:
// http://graphics.stanford.edu/~seander/bithacks.html
static readonly int[] m_Log2DeBruijn32 =
{
0, 9, 1, 10, 13, 21, 2, 29,
11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7,
19, 27, 23, 6, 26, 5, 4, 31
};
public static int Log2_DeBruijn(uint value)
{
// Round down to one less than a power of 2.
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
var index = (value * 0x07C4ACDDU) >> 27;
return m_Log2DeBruijn32[index];
}
}
Here are the execution times of all two implementations (lower is better):
| Method | Mean | Error | StdDev |
|---|---|---|---|
| Log2_Trivial | 4.587 ns | 0.0325 ns | 0.0288 ns |
| Log2_DeBruijn | 1.256 ns | 0.0068 ns | 0.0063 ns |
This is a vast improvement over the previous version but we can do even better.
Meet the Intel 80386, a 32-bit microprocessor introduced in 1985.
It brought the Bit Scan Reverse (BSR) instruction that does exactly the same what we want to achieve by Log2 using just a small fraction of CPU cycles.
Chances are that your machine runs on a descendant of that influential CPU, be it AMD Ryzen or Intel Core.
So how can we use the low-level BSR instruction from high-level .NET?
This is why Gapotchenko.FX.Runtime.CompilerServices.Intrinsics class exists.
It provides the ability to define an intrinsic implementation of a method with MachineCodeIntrinsicAttribute.
Let's see how:
using Gapotchenko.FX.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
class BitOperations
{
// Use static constructor to ensure that intrinsic methods are initialized (compiled) before they can be used
static BitOperations() => Intrinsics.InitializeType(typeof(BitOperations));
static readonly int[] m_Log2DeBruijn32 =
{
0, 9, 1, 10, 13, 21, 2, 29,
11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7,
19, 27, 23, 6, 26, 5, 4, 31
};
// Define machine code intrinsic for the method
[MachineCodeIntrinsic(Architecture.X64, 0x0f, 0xbd, 0xc1)] // BSR EAX, ECX
[MethodImpl(MethodImplOptions.NoInlining)]
public static int Log2_Intrinsic(uint value)
{
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
var index = (value * 0x07C4ACDDU) >> 27;
return m_Log2DeBruijn32[index];
}
}
Log2_Intrinsic method defines a custom attribute that provides a machine code for BSR EAX, ECX instruction.
Machine code is tied to CPU architecture and this is reflected in the attribute as well.
Please note that besides using MachineCodeIntrinsicAttribute to define method intrinsic implementations,
BitOperations class should use a static constructor to ensure that the corresponding methods are initialized (compiled) before they are called.
Here are the execution times of all three implementations (lower is better):
| Method | Mean | Error | StdDev |
|---|---|---|---|
| Log2_Trivial | 4.587 ns | 0.0325 ns | 0.0288 ns |
| Log2_DeBruijn | 1.256 ns | 0.0068 ns | 0.0063 ns |
| Log2_Intrinsic | 1.038 ns | 0.0660 ns | 0.0947 ns |
Log2_Intrinsic is a clear winner.
The intrinsic compiler may or may not apply machine code to a method depending on the current app host environment. When intrinsic is not applied, the original method implementation is used, thus providing a graceful, albeit less performant, fallback.
Gapotchenko.FX.Runtime.CompilerServices.IntrinsicServicesGapotchenko.FX.Runtime.CompilerServices.MachineCodeIntrinsicAttributeLet's continue with a look at some other modules provided by Gapotchenko.FX:
Symbol ✱ denotes an advanced module.
Symbol ✱✱ denotes an expert module.
Or take a look at the full list of modules.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 is compatible. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 is compatible. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 1 NuGet packages that depend on Gapotchenko.FX.Runtime.CompilerServices.Intrinsics:
| Package | Downloads |
|---|---|
|
Gapotchenko.FX.Numerics
The module provides hardware-accelerated operations for numeric data types. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.7.2 | 369 | 5/16/2026 |
| 2026.6.2 | 373 | 3/29/2026 |
| 2026.5.3 | 387 | 2/24/2026 |
| 2026.4.2 | 353 | 2/4/2026 |
| 2026.3.5 | 352 | 1/29/2026 |
| 2026.2.2 | 362 | 1/25/2026 |
| 2026.1.5 | 369 | 1/13/2026 |
| 2025.1.45 | 433 | 12/25/2025 |
| 2025.1.27-beta | 424 | 10/9/2025 |
| 2025.1.26-beta | 483 | 8/30/2025 |
| 2025.1.25-beta | 792 | 7/22/2025 |
| 2025.1.24-beta | 429 | 7/16/2025 |
| 2025.1.23-beta | 373 | 7/12/2025 |
| 2024.2.5 | 606 | 12/31/2024 |
| 2024.1.3 | 502 | 11/10/2024 |
| 2022.2.7 | 11,311 | 5/1/2022 |
| 2022.2.5 | 2,036 | 5/1/2022 |
| 2022.1.4 | 2,046 | 4/6/2022 |
| 2021.2.21 | 1,314 | 1/21/2022 |