С#, Заполнение массива одним значением.
Практического значения эта задача обычно не имеет (на самом деле применение есть, покажу позже), но, тем не менее, иногда ее дают в качестве учебной задачи. Попробуем ее решить на C#.
Примечание: Создаваемый по умолчанию массив, автоматически заполняется нолями (
0x00
).А нам, как раз, наоборот, надо создать массив с паттерном
0xFF
или 0xAA
.Я думаю, оно всем понятно. Создать массив и заполнить его нужными значениями:
int items = 536870912;
byte[] tArr = new byte[items];
for (int i = 0; i < items; i++)
{
tArr[i] = 0xFF;
}
Тут мы в цикле присваиваем каждому элементу массива значение
0xFF
.- Оно медленное.
+ Оно простое и с использованием безопасного кода.
Некто попытался оптимизировать прошлое решение, используя
Array.Copy()
, думая, что эта функция быстрее работает с памятью.Что решение "в лоб", что "
Array.Copy()
" с распополамленным циклом работают одинаково, точнее, получилось даже медленнее (в конце статьи будет итоговая таблица):int items = 536870912;
byte[] tArr = new byte[items];
tArr[0] = 0xFF;
for (int i = 1; i <= items / 2; i *= 2)
{
Array.Copy(tArr, 0, tArr, i, i);
Array.Copy(tArr, 0, tArr, i, items - i);
}
Прямая работа с памятью сильно обходит .NET по скорости, так что самый оптимальный способ для такой задачи - использовать небезопасный код.
public static class FillArray
{
[DllImport("msvcrt.dll",
EntryPoint = "memset",
CallingConvention = CallingConvention.Cdecl,
SetLastError = false)]
private static extern IntPtr MemSet(IntPtr dest, int value, int count);
public static byte[] FillBytes(int Length, byte Value)
{
byte[] Arr = new byte[Length];
GCHandle GCH = GCHandle.Alloc(Arr, GCHandleType.Pinned);
MemSet(GCH.AddrOfPinnedObject(), (int)Value, Length);
return Arr;
}
В свою программу мы импортировали функцию
memset
из библиотеки msvcrt.dll
, т.е. смогли получить контроль над памятью. И заполнили нужным числом массив. Поскольку, за нас это делали библиотеки C++ и функции ОС, все оказалось быстро.Сравнительная таблица скорости работы разных алгоритмов заполнения массива (массив 500 Мб).
For | 00:00:04.4212528 |
For+Array.Copy() | 00:00:04.6952685 |
MemSet (msvcrt.dll) | 00:00:00.2360135 |
Random bytes (RNGCryptoServiceProvider) | 00:00:06.1143497 |
Сравнение алгоритмов в источнике.

Тестовый пример (для этого и предыдущего [копия] поста) на GitHub
Источник
Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2021/01/13/s-za