CSHARP_GEPARD Telegram 140
Dictionary.AlternateLookup #память #скорость

Несколько лет назад я устраивался в компанию, которая дала тестовое задание. Его суть - показать максимальную скорость и минимальную аллокацию при обработке большого объема данных. Что-то вроде "посчитать количество слов в документе" (я упрощаю).

Одна из основных проблем в подобной задаче - поиск ключа (слова) в большом словаре Dictionary<string, int> и инкремент значения (количества). В то время мне пришлось взять код обычного Dictionary и модернизировать его так, чтобы он принимал ReadOnlySpan<char> в качестве ключа - так я пытался не аллоцировать строки, которые уже существуют в словаре. Инкремент был выполнен в стиле современного CollectionsMarshal.GetValueRefOrAddDefault. Решение коллегам понравилась и меня взяли на работу.

В современном .NET 9 эта задача решается максимально просто, так как нам предоставили прекрасный метод словаря GetAlternateLookup, возвращающий специальную структуру, которая может принимать в качестве ключа то, что сам программист считает сравнимым с ключом словаря.

var dic = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var lookup = dic.GetAlternateLookup<ReadOnlySpan<char>>();

foreach (ReadOnlySpan<char> word in wordCollection)
{
CollectionsMarshal.GetValueRefOrAddDefault(lookup, word, out _)++;
}


В данном примере, сравнение ReadonlySpan<char> с типом string возможно потому, что у StringComparer существует реализация интерфейса IAlternateEqualityComparer<ReadOnlySpan<char>, string>. Если ознакомиться с его кодом, то мы видим, что этот интерфейс требует не только реализовать операции сравнения, но и метод создания string из ReadOnlySpan<char>. Таким образом, lookup имеет возможность не только сравнивать значения ключа, но и, в случае его отсутствия, создавать в словаре запись с этим ключом.

Бенчмарк в комментариях. Он содержит сравнение наивного подхода с реализацией через AlternateLookup. В наивном подходе мы создаём строки для поиска наличия ключа, а в случае с AlternateLookup строки создаются только тогда, когда запись в словаре отсутствует. Более сложные сравнения с созданием специального словаря я опущу, хотя в этом случае, как мне кажется, всё-таки возможно выжать ещё немного скорости.
🔥24👍182



tgoop.com/csharp_gepard/140
Create:
Last Update:

Dictionary.AlternateLookup #память #скорость

Несколько лет назад я устраивался в компанию, которая дала тестовое задание. Его суть - показать максимальную скорость и минимальную аллокацию при обработке большого объема данных. Что-то вроде "посчитать количество слов в документе" (я упрощаю).

Одна из основных проблем в подобной задаче - поиск ключа (слова) в большом словаре Dictionary<string, int> и инкремент значения (количества). В то время мне пришлось взять код обычного Dictionary и модернизировать его так, чтобы он принимал ReadOnlySpan<char> в качестве ключа - так я пытался не аллоцировать строки, которые уже существуют в словаре. Инкремент был выполнен в стиле современного CollectionsMarshal.GetValueRefOrAddDefault. Решение коллегам понравилась и меня взяли на работу.

В современном .NET 9 эта задача решается максимально просто, так как нам предоставили прекрасный метод словаря GetAlternateLookup, возвращающий специальную структуру, которая может принимать в качестве ключа то, что сам программист считает сравнимым с ключом словаря.

var dic = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var lookup = dic.GetAlternateLookup<ReadOnlySpan<char>>();

foreach (ReadOnlySpan<char> word in wordCollection)
{
CollectionsMarshal.GetValueRefOrAddDefault(lookup, word, out _)++;
}


В данном примере, сравнение ReadonlySpan<char> с типом string возможно потому, что у StringComparer существует реализация интерфейса IAlternateEqualityComparer<ReadOnlySpan<char>, string>. Если ознакомиться с его кодом, то мы видим, что этот интерфейс требует не только реализовать операции сравнения, но и метод создания string из ReadOnlySpan<char>. Таким образом, lookup имеет возможность не только сравнивать значения ключа, но и, в случае его отсутствия, создавать в словаре запись с этим ключом.

Бенчмарк в комментариях. Он содержит сравнение наивного подхода с реализацией через AlternateLookup. В наивном подходе мы создаём строки для поиска наличия ключа, а в случае с AlternateLookup строки создаются только тогда, когда запись в словаре отсутствует. Более сложные сравнения с созданием специального словаря я опущу, хотя в этом случае, как мне кажется, всё-таки возможно выжать ещё немного скорости.

BY C# Heppard




Share with your friend now:
tgoop.com/csharp_gepard/140

View MORE
Open in Telegram


Telegram News

Date: |

To view your bio, click the Menu icon and select “View channel info.” Among the requests, the Brazilian electoral Court wanted to know if they could obtain data on the origins of malicious content posted on the platform. According to the TSE, this would enable the authorities to track false content and identify the user responsible for publishing it in the first place. In 2018, Telegram’s audience reached 200 million people, with 500,000 new users joining the messenger every day. It was launched for iOS on 14 August 2013 and Android on 20 October 2013. The court said the defendant had also incited people to commit public nuisance, with messages calling on them to take part in rallies and demonstrations including at Hong Kong International Airport, to block roads and to paralyse the public transportation system. Various forms of protest promoted on the messaging platform included general strikes, lunchtime protests and silent sit-ins. SUCK Channel Telegram
from us


Telegram C# Heppard
FROM American