Оператор Switch вместо оператора set

Я провожу тест о структурах ref и text-ValueType
и сделайте шаг в это сомнение, работая в конструкторах структур.

По-видимому, оператор switch, управляющий переменной ref с помощью цикла в стиле i, может быть
быстрее, чем ручная установка позиций массива в поле структуры.
Я не уверен в достоверности такого теста в методе оператора верхнего уровня, но

вот код

using System.Diagnostics;

const string testText = $"""
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.  
    Quisque orci purus, vulputate vulputate
    """;
const   int     load_Steps  =  250;
CharblockExample bySetBlock ;
CharblockExample bySwitchBlock;
var watcher = Stopwatch.StartNew();
var results = new List<(TimeSpan tic1, TimeSpan tic2)>();
try
{
    for (int i = 0; i < load_Steps; i++)
    {
        var start_tics = watcher.Elapsed;
        bySwitchBlock = new(testText.AsSpan(), true);
        var ticBlock2 = watcher.Elapsed - start_tics;

        start_tics = watcher.Elapsed;
        bySetBlock = new(testText.AsSpan(), false);
        var ticBlock1 = watcher.Elapsed - start_tics;
        
        Console.WriteLine($"{nameof(bySetBlock)} and {nameof(bySwitchBlock)}: {ticBlock1} vs {ticBlock2}");
        results.Add((ticBlock1, ticBlock2));
    }
}
finally
{
    watcher.Stop();
    Console.WriteLine();
    var overall_1 = results.Sum(element => element.tic1.Microseconds);
    var overall_2 = results.Sum(selector => selector.tic2.Microseconds);
    var overall_result = overall_1 - overall_2;

    Console.WriteLine($"overall analysis: {(overall_1 is < 0
        ? $"{nameof(bySetBlock)}    was {Math.Abs(overall_result)} ms faster than {nameof(bySwitchBlock)}" 
        : $"{nameof(bySwitchBlock)} was {Math.Abs(overall_result)} ms faster than {nameof(bySetBlock)}"
    )}");
}

public readonly ref struct CharblockExample
{
    private readonly int inputtedLength;
    private readonly bool _input = false;
    private readonly char //char spots
    #region Char-Spots
        _0, _1, _2, _3, _4, _5,
        _6, _7, _8, _9, _10;
    #endregion

    public CharblockExample(ReadOnlySpan<char> chars, bool performTest)
    {
        _input = true;
        Span<char> arr = stackalloc char[MAX_LENGTH];
        inputtedLength = chars.Length;
        if (chars.Length > MAX_LENGTH)
            throw new ArgumentOutOfRangeException(nameof(chars), $"""
                The provided char array is longer than the max of 256 chars for this block.
                """);

        for (int i = 0; i < MAX_LENGTH; i++)
        {
            if (i >= chars.Length) break;
            arr[i] = chars[i];
        }

        if (performTest)
        {
            int pos = 0;
            ref var _ref = ref _1;
            while (pos < MAX_LENGTH - 1)
            {
                switch (pos)
                {
                    case 0: _ref = ref _0; break;
                    case 1: _ref = ref _1; break;
                    case 2: _ref = ref _2; break;
                    case 3: _ref = ref _3; break;
                    case 4: _ref = ref _4; break;
                    case 5: _ref = ref _5; break;
                    case 6: _ref = ref _6; break;
                    case 7: _ref = ref _7; break;
                    case 8: _ref = ref _8; break;
                    case 9: _ref = ref _9; break;
                    case 10: _ref = ref _10; break;
                }
                pos++;
                _ref = arr[pos];
            }
        }
        else
        {
            _0 = arr[0]; _1 = arr[1]; _2 = arr[2]; _3 = arr[3]; _4 = arr[4];
            _5 = arr[5]; _6 = arr[6]; _7 = arr[7]; _8 = arr[8]; _9 = arr[9];
            _10 = arr[10];
        }
    }    
    public char[] CharArr => new[]
    {
        _0,   _1,   _2,   _3,   _4,   _5,
        _6,   _7,   _8,   _9,  _10
    };

    private const int MAX_DISPLAYABLE = 15;
    private const int MAX_LENGTH = 256;
}

это мой результат после полного выполнения:

общий анализ: bySwitchBlock был на 1240 мс быстрее, чем bySetBlock

  • По моему мнению, только установка без проверки какой-либо логической логики или продвижения целочисленного индексатора должна быть быстрее, это просто встроенное выполнение команд для того, что я вижу

Я протестировал структуру CharblockExample из вашей первой версии с помощью BenchmarkDotNet. Использование переключателя примерно в 2 раза медленнее.

Sweeper 08.08.2023 05:22

@Sweeper, я собираюсь поискать в BenchmarkDotNet, это кажется действительно полезным. Можете ли вы опубликовать результаты комментариев в качестве ответа, чтобы я мог отметить как ответ?

James Jonatah 08.08.2023 05:25

Что вы подразумеваете под «текстовым типом значения»? С# не поддерживает строковые типы (это TypeScript)

Dai 08.08.2023 05:25
Thread.Sleep(TimeSpan.FromSeconds(eachPause_s)) <-- Thread.Sleep очень неточен и использовать его здесь совершенно бессмысленно.
Dai 08.08.2023 05:25

@Dai, это не поддерживает. Я пытаюсь реализовать это каким-то образом для хранения текста в стеке, что было бы действительно круто

James Jonatah 08.08.2023 05:26
rivate readonly char //char spots не имеет преимуществ перед полем fixed char[10].
Dai 08.08.2023 05:26

@JamesJonatah «Я пытаюсь каким-то образом реализовать это для хранения текста в стеке» - вы не можете и не должны.

Dai 08.08.2023 05:27

@Dai, не могу получить размер структуры с полем массива, что является обязательным, и это печально.

James Jonatah 08.08.2023 05:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Тестирование CharblockExample из первой версии вашего вопроса с помощью BenchmarkDotNet дает результат, что использование switch примерно в 2 раза медленнее, чем его отсутствие.

BenchmarkDotNet v0.13.7, Windows 10 (обновление 10.0.19045.3086/22H2/2022)

ЦП Intel Core i7-6700 3,40 ГГц (Skylake), 1 ЦП, 8 логических и 4 физических ядра

Пакет SDK для .NET 7.0.304

[Хост]: .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2

Задание по умолчанию: .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2

Метод Иметь в виду Ошибка стандартное отклонение Выключатель 363,3 нс 7,18 нс 11,18 нс NoSwitch 170,2 нс 3,44 нс 3,96 нс

Этого следовало ожидать. Вы выполняете много дополнительной работы — контролируете цикл, прыгаете с таблицей переходов и т. д. Я также не удивлюсь, если джиттер сможет распознать шаблон и оптимизировать серию назначений в коде без переключателя в что-то намного быстрее.

Вот эталонный код:

public class Benchmark
{
    const string testText = $"""
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.  
    Quisque orci purus, vulputate vulputate mattis quis, 
    accumsan in turpis. Vestibulum quis sapien iaculis, 
    pulvinar magna sed, lacinia lectus. Donec nec felis nec
     metus dictum aliquet vel non.
    """;

    [Benchmark]
    public CharblockExample Switch() => new CharblockExample(testText, true);

    [Benchmark]
    public CharblockExample NoSwitch() => new CharblockExample(testText, false);
}

public class Program
{
    public static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Benchmark>();
    }
}

Как правило, такой код микробенчмаркинга дает довольно неточные результаты. На конечный результат может повлиять множество внешних факторов. Вам следует использовать подходящий инструмент для сравнительного анализа, такой как BenchmarkDotNet.

@AdrianHHH о боже. Спасибо за напоминание. Я понятия не имею, как я пропустил это.

Sweeper 09.08.2023 01:41

Другие вопросы по теме