Практического значения эта задача обычно не имеет (на самом деле применение есть, покажу позже), но, тем не менее, иногда ее дают в качестве учебной задачи. Попробуем ее решить на 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
Pingback: C#, сгенерировать строку нужной длины из одного символа. | Персональный блог Толика Панкова
Pingback: C#, генератор файлов (нужного количества и с определенным содержимым). | Персональный блог Толика Панкова