Zaujímavé linky #11

Po dlhšej dobe sa mi zas podarilo nazbierať par zaujímavých dotnetových odkazov a nugetov.

Entity Framework Core knižnice

O tom, že je Entity Framework Core modulárnejší svedčí aj to, že preň vznikajú rôzne rozšírenia.

EFCore.CheckConstraints

Pridáva to, že sa v DDL objavia constrainty, ktoré sú definované pre model. V takom prípade Entity Framework Core uspokojí aj tých najviac hardcore databázistov.

EFCore.SqlServer.HierarchyId

Táto knižnica pridáva podporu HierarchyId pre MS SQL do Entity Frameworku Core. HierarchyId rieši ukladanie a prácu s hierarchickými dátami (napríklad stromy) v MS SQL. Je to vec, o ktorej sa málo vie, ale stojí za povšimnutie.

Mapperly

Pekná a hlavne funkčná knižnica – source generátor, ktorá sa dá použiť ako náhrada Automapperu, no s tým, že to všetko vygeneruje pri kompilácii. Vo svojom kóde som zatiaľ nenašiel use-case, ktoré by pri migrácii s automapperu nezvládla, aj keď občas k tomu treba pristupovať inak, navyše zvláda aj nullable typy a vie (no treba to zapnúť) upozorniť na nesprávne mapovanie už počas prekladu.

Skúšal som aj iné knižnice na generovanie mapovania DTO-čiek, no táto sa používala najlepšie/najpohodlnejšie.

Dotnetový workflow engine

Náhodou som narazil na tento workflow engine pre .Net Core. Má v sebe aj webový dizajnér, kde je možné si „nakresliť“ workflow a riadením toku, nejakými webovými vecami, kúskami Javascriptu, Liquid-u, poprípade dotnetovými akciami. Podporuje aj asynchróone akcie (tie, ktoré čakajú na ľudskú interakciu).

Môže sa to niekomu hodiť.

https://elsa-workflows.github.io/elsa-core/

BouncyCastle 2

Vyšla druhá verzia knižnice BouncyCastle, ktorá obsahuje hádam všetky kryptografické algoritmy a PKI štruktúry na ktoré si človek spomenie (vrátane divných hash algoritmov, eliptických kriviek, dokonca implementuje TSL-ko) a to všetko v čisto dotnetovej implementácii bez závislostí. To znamená, že pôjde na akomkoľvek operačnom systéme (pozdravujem linuxové OpenSSL depency hell) a dokonca aj v browseri.

Po novom sa nuget volá BouncyCastle.Cryptography, pretože konečne zahodili podporu starých frameworkov (nedávne verzie podporovali ešte .Net Framework 2). Práve starým verziám frameworku a tým, že to bol port ešte z Javy 1.7 bol podriadený štýl písania kódu (žiadne generiká, Linq,…).

Svitá na lepšie časy, tak sa možno dočkáme podpory Span-u alebo async streamov. V každom prípade, to nie je ľahká úloha vzhľadom na rozsah knižnice.

V tejto verzii pristali aj dva moje drobné merge-requesty.

ComputeSharp

ComputeSharp je sada knižníc a source generátor, ktorý umožňuje, aby sa C# programátor stal GPU programátor (spúšťal svoje výpočty s mohutným paralelizmom na grafickej karte).

A to sa vyplatí!

Funguje to tak, že sa do projektu pridá jeden nuget, implementuje sa jedno rozhranie, ktoré predstavuje computed HLSL sharder (source generátor dogeneruje typy, ktoré podporuje grafický procesor) následne source generátor vygeneruje bytekód pre HLSL a obslužný kód, ktorý umožňuje spustenie výpočtu na stovkách jadier grafickej karty.

Keď som to videl bol som veľmi nadšený, pretože už žiadne očuchávanie IL-kódu v postbuild evente, alebo písanie do textového súboru bez intelisense, či obmedzenie na expression trees (tam môžem napísať čokoľvek a padne to až v runtime). Ale priamo vo VS mám plnohodnotnú intelisense, dokonca, keď tam napíšem niečo, čo sa nedá preložiť vidím to hneď ako chybu. Za mňa jedna s najzaujímavejších ukážok source generátora.

Tu je prednáška s .Net Conf:

A pridávam aj môj testovací projekt – vykresanie mandelbrotovej množiny:

using ComputeSharp;

namespace ComputeSharpExample;

internal class Program
{
    public static void Main(string[] args)
    {
        int width = 15_000;
        int height = 11_000;

        var device = GraphicsDevice.GetDefault();

        using var texture = device.AllocateReadWriteTexture2D<Rgba32, float4>(width, height, AllocationMode.Default);

        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        stopwatch.Start();
        device.For(width, height, new MandelbrotKernel(texture, new Coordinates(-2.3f, -1.0f, 3.0f, 2.2f)));
        stopwatch.Stop();

        texture.Save("test.png");

        Console.WriteLine("Generate in {0} ms for {1} pixels.", stopwatch.ElapsedMilliseconds, width * height);
    }
}

public readonly struct Coordinates
{
    public readonly float2 Start;
    public readonly float2 Size;

    public Coordinates(float x, float y, float width, float height)
    {
        this.Start = new float2(x, y);
        this.Size = new float2(width, height);
    }
}

[AutoConstructor]
[EmbeddedBytecode(DispatchAxis.XY)]
public readonly partial struct MandelbrotKernel : IComputeShader
{
    public readonly ReadWriteTexture2D<Rgba32, float4> buffer;
    public readonly Coordinates coordinates;

    private const int mbIterations = 75;

    public void Execute()
    {
        float2 xy = ThreadIds.Normalized.XY * this.coordinates.Size + this.coordinates.Start;

        int i = 0;
        float zReal = 0.0f;
        float zImagnary = 0.0f;

        while (zReal * zReal + zImagnary * zImagnary < 4.0 && i < mbIterations)
        {

            float zRealTmp = zReal * zReal - zImagnary * zImagnary + xy.X;
            zImagnary = 2.0f * zReal * zImagnary + xy.Y;
            zReal = zRealTmp;
            i++;
        }

        float gray = (float)i / (float)mbIterations;
        this.buffer[ThreadIds.XY] = CreateColor(gray);
    }

    private static float4 CreateColor(float greyValue)
    {
        if (greyValue > 1.0)
        {
            return new float4(0.0f, 0.0f, 0.0f, 1.0f);
        }

        return CalculatePallete(Hlsl.Frac(greyValue + 0.5f),
            new float3(0.5f, 0.5f, 0.5f),
            new float3(0.5f, 0.5f, 0.5f),
            new float3(1.0f, 1.0f, 1.0f),
            new float3(0.0f, 0.1f, 0.2f));
    }

    private static float4 CalculatePallete(float t, float3 a, float3 b, float3 c, float3 d)
    {
        float3 tmp = a + b * Hlsl.Cos(6.28318f * (c * t + d));
        return new float4(tmp, 1.0f);
    }
}

A tu je výsledok, no s trochu inými parametrami:

No treba si uvedomiť, že jadrá grafickej karty nie sú CPU a napríklad nedokážu pracovať s bajtami a tiež majú obmedzenie aké vstupné a výstupné dáta dostanú. Tiež je funkcionalita obmedzená na DirectX.

Verím, že táto knižnica svoje využitie nájde a dúfam, že aj iné ako ťažba kryptomien.

2 lajkov

Thinktecture.EntityFrameworkCore

pridava napriklad podporu temptables, alebo rozsiruje moznosti queryovania o RowNumber, alebo table hints

1 lajk

Vdaka, RowNumber je velmi uzitocna featura.