Skip to content

Commit

Permalink
Release 2020.1
Browse files Browse the repository at this point in the history
  • Loading branch information
hrumhurum committed Nov 5, 2020
2 parents 9868031 + 956197a commit a04594c
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 11 deletions.
10 changes: 5 additions & 5 deletions Source/Gapotchenko.FX.Reflection.Loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ The redirects are automatically created by build tools, and then put to correspo
Assembly binding redirects work well for apps, but get completely broken if you want to employ them for dynamically loaded assemblies like plugins.
The default .NET loader simply ignores `.config` files of .DLL assemblies!

`Gapotchenko.FX.Reflection.Loader` solves this. Just add the following code early at the assembly lifecycle:
`Gapotchenko.FX.Reflection.Loader` solves this. Just add the following code to a place which gets executed at the early stage of the assembly lifecycle:

``` csharp
AssemblyLoader.Activate()
Expand Down Expand Up @@ -255,7 +255,7 @@ namespace MyPlugin
```

There are a lot of projects that may need this: T4 templates, MSBuild tasks, plugins, extensions etc.
Basically everything that gets dynamically loaded and depends on one or more NuGet packages.
Basically everything that gets dynamically loaded and depends on one or more NuGet packages with mishmash of versions.

<hr/>

Expand All @@ -267,11 +267,11 @@ This is done to avoid chicken & egg dilemma.
In this way, the default .NET assembly loader can always load the assembly despite the possible variety of different NuGet packages that can be used in the given project.

Another point to consider is **how to select a point of assembly loader installation** that is early enough in the assembly lifecycle.
This tends to be trivial for an app: the first few lines of main entry point are good to go.
But it may be hard to do or totally infeasible for a class library with a wide public API surface.
This tends to be trivial for an app: the first few lines of the main entry point are good to go.
But it may be hard to do for a class library. Sometimes it gets totally infeasible when public API surface of a library gets wide enough.
To overcome that dilemma, assembly loader can be installed at module initializer of a class library.

[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET.
[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. Another option is to use more specialized tool like [Eazfuscator.NET](https://www.gapotchenko.com/eazfuscator.net) that provides not only [module initialization functionality](https://help.gapotchenko.com/eazfuscator.net/63/sensei-features/module-initializers), but also intellectual property protection.

<hr/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ using just a small fraction of cycles.
Chances are your machine runs on a descendant of that influential CPU, be it AMD Ryzen or Intel Core.
So how can we use the `BSR` instruction from .NET?

This is why `Gapotchenko.FX.Runtime.CompilerServices.Intrinsics` class was created.
It allows to provide an intrinsic implementation of a method with `MachineCodeIntrinsicAttribute`. Let's see how:
This is why `Gapotchenko.FX.Runtime.CompilerServices.Intrinsics` class exists.
It provides an ability to define intrinsic implementation of a method with `MachineCodeIntrinsicAttribute`. Let's see how:

``` csharp
using Gapotchenko.FX.Runtime.CompilerServices;
Expand All @@ -81,6 +81,7 @@ using System.Runtime.InteropServices;

class BitOperations
{
// Use static constructor to ensure that intrinsic methods are initialized (compiled) before they are called
static BitOperations() => Intrinsics.InitializeType(typeof(BitOperations));

static readonly int[] m_Log2DeBruijn32 =
Expand All @@ -91,6 +92,7 @@ class BitOperations
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)
Expand All @@ -110,9 +112,10 @@ class BitOperations
`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.

`BitOperations` class now has a static constructor that ensures that intrinsic methods of the type are initialized (compiled) before they are used.
Please note that besides using `MachineCodeIntrinsicAttribute` to define method intrinsic implementations,
`BitOperations` class **should** use a static constructor to ensure that corresponding methods are initialized (compiled) before they are called.

Here are the execution times of those implementations (lower is better):
Here are the execution times of all three implementations (lower is better):

| Method | Mean | Error | StdDev |
|--------------- |---------:|----------:|----------:|
Expand Down
2 changes: 1 addition & 1 deletion Source/Gapotchenko.FX.Text/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ That's why `Gapotchenko.FX.Text` module provides a set of so called regex trampo
They look exactly like `Equals`, `StartsWith`, `EndsWith`, `IndexOf` but work on regex patterns instead of raw strings.
They also end with `Regex` suffix in their names, so `Equals` becomes `EqualsRegex`, `StartsWith` becomes `StartsWithRegex` and so on.

This is how a regex trampoline can be used for the given sample to meet the new requirements by a single line change:
This is how a regex trampoline can be used for the given sample in order to meet the new requirements by a single line change:

``` csharp
using Gapotchenko.FX.Text.RegularExpressions;
Expand Down
6 changes: 5 additions & 1 deletion Source/Gapotchenko.FX/Optional`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
namespace Gapotchenko.FX
{
/// <summary>
/// <para>
/// Represents an optional value.
/// It is similar to <see cref="Nullable{T}"/>, but can also operate with a value of a reference type.
/// </para>
/// <para>
/// <see cref="Optional{T}"/> is similar to <see cref="Nullable{T}"/> but can also operate when <see cref="T"/> is a reference type.
/// </para>
/// </summary>
/// <typeparam name="T">The underlying type of the <see cref="Optional{T}"/> generic type.</typeparam>
[Serializable]
Expand Down

0 comments on commit a04594c

Please sign in to comment.