Навіщо взагалі використовувати клас C # System.Random замість System.Security.Cryptography.RandomNumberGenerator?


85

Чому хтось взагалі використовуватиме "стандартний" генератор випадкових чисел від System.Random замість того, щоб завжди використовувати криптографічно захищений генератор випадкових чисел від System.Security.Cryptography.RandomNumberGenerator (або його підкласи, оскільки RandomNumberGenerator абстрактний)?

Нейт Лоусон розповідає нам у своїй презентації Google Tech Talk " Crypto Strikes Back " на хвилині 13:11 не використовувати "стандартні" генератори випадкових чисел з Python, Java та C #, а замість цього використовувати криптографічно безпечну версію.

Я знаю різницю між двома версіями генераторів випадкових чисел (див. Питання 101337 ).

Але яке обгрунтування є не завжди використання безпечного генератора випадкових чисел? Навіщо взагалі використовувати System.Random? Можливо, продуктивність?


7
Якого ви віддаєте перевагу друкувати?
Macha

13
Занадто багато людей серйозно використовують це як виправдання того, що вони роблять (як правило, не вголос). Код читається більше, ніж написаний, кого цікавлять тривіальні різниці довжини?
Mark Sowul

3
Але в будь-якому випадку, чому ви повинні використовувати криптографічні RNG, якщо ви не робите криптографії?
Марк Совул

3
@Macha, ось для чого псевдоніми ->using R = System.Security.Cryptography.RandomNumberGenerator; R.Create();
cchamberlain

Відповіді:


144

Швидкість і намір. Якщо ви генеруєте випадкове число і не потребуєте безпеки, навіщо використовувати повільну крипто-функцію? Вам не потрібна безпека, то навіщо змушувати когось іншого думати, що номер можна використовувати для чогось безпечного, коли цього не буде?


30
Мені дуже подобається аргумент про намір.
Lernkurve

12
Слід зазначити, що Random.GetNext далеко не добре «розподіляє» випадкові числа по спектру, особливо в потоковому середовищі. Я зіткнувся з цією проблемою, коли писав програму для тестування різних рішень проблеми Rand7 від Rand5. Під час швидкого різьбового тесту, який зараз містив 100000 випадкових чисел від 0 до 10, 82470 згенерованих чисел дорівнювали 0. Я бачив подібні розбіжності в своїх попередніх тестах. Криптографія випадкова дуже рівномірна у розподілі чисел. Думаю, урок полягає в тому, щоб завжди перевіряти свої випадкові дані, щоб переконатися, що вони є «досить випадковими» для ваших потреб.
Kristoffer L

35
@Kristoffer Я думаю, ти зловживав Random. Дозвольте мені здогадатися: Ви створили новий екземпляр Randomкласу для кожного числа, який, оскільки він засіяний грубим таймером, буде засіяний тим самим значенням для інтервалу приблизно 1-16 мс.
CodesInChaos

15
@CodesInChaos: Крім того, існує умова перегону, Randomяка змушує його повертати всі 0, коли один і той же об'єкт використовується з декількох потоків.
BlueRaja - Danny Pflughoeft

3
@KristofferL: Див. Коментар вище, також див. Цю відповідь
BlueRaja - Danny Pflughoeft

65

Окрім швидкості та більш корисного інтерфейсу ( NextDouble()тощо), також можна зробити повторювану випадкову послідовність за допомогою фіксованого значення насіння. Це досить корисно, серед іншого під час тестування.

Random gen1 = new Random();     // auto seeded by the clock
Random gen2 = new Random(0);    // Next(10) always yields 7,8,7,5,2,....

2
А ще є BitConverter.ToInt32 (значення байта [], int startIndex), яке може бути простіше зрозуміти. ;)
sisve

7
Ян Белл та Девід Брабен використовували генератор випадкових випадків у комп'ютерній грі Elite, щоб створити величезний перелік планет та їх атрибутів (розмір тощо) з дуже обмеженою пам'яттю. Це також покладається на генератор, що створює детермінований шаблон (із затравки) - якого Crypto, очевидно, не надає (за задумом.) Тут є додаткова інформація про те, як вони це зробили тут: wiki.alioth.net/index.php / Random_number_generator і книга "Нескінченний ігровий Всесвіт: Математичні прийоми" ISBN: 1584500581 має більш загальне обговорення таких методів.
Даніель Джеймс Брайарс,

7
Майте на увазі, що MSDN не гарантує, що ця властивість зберігатиметься у версіях .NET: "Впровадження генератора випадкових чисел у класі Random не гарантується незмінним у основних версіях .NET Framework."
Роман Старков

2
@phoog "Як результат, ваш код програми не повинен припускати, що одне і те ж насіння призведе до однакової псевдовипадкової послідовності в різних версіях .NET Framework." - Не знаю, здається мені досить зрозумілим. Однак я не здивуюсь, якщо вони не зможуть змінити це на практиці, не порушуючи існуючі програми, незважаючи на це попередження.
Роман Старков,

2
@phoog: Ви говорите одне, а потім прямо протилежне йому. Ви прямо суперечите собі.
Timwi

53

Перш за все у презентації, яку ви зв’язали, лише з метою безпеки йдеться про випадкові числа. Тому він не стверджує, що Randomце погано для цілей, що не стосуються безпеки.

Але я справді стверджую, що це так. Реалізація .net 4 Randomнедолікована кількома способами. Я рекомендую використовувати його лише в тому випадку, якщо ви не дбаєте про якість своїх випадкових чисел. Я рекомендую використовувати кращі сторонні реалізації.

Помилка 1: посів

Конструктор за замовчуванням насіння з поточним часом. Таким чином, всі екземпляри, Randomстворені за допомогою конструктора за замовчуванням за короткий проміжок часу (приблизно 10 мс), повертають однакову послідовність. Це задокументоване та «побічний проект». Це особливо дратує, якщо ви хочете багатопотоковий код, оскільки ви не можете просто створити екземплярRandom на початку виконання кожного потоку.

Обхідний шлях полягає в тому, щоб бути надто обережним при використанні конструктора за замовчуванням та заводити вручну, коли це необхідно.

Інша проблема тут полягає в тому, що насіннєвий простір досить малий (31 біт). Отже, якщо ви генеруєте 50 тисяч екземплярів Randomіз абсолютно випадковими насінинами, ви, ймовірно, отримаєте одну послідовність випадкових чисел двічі (через парадокс дня народження ). Тож висіти вручну теж непросто.

Помилка 2: Розподіл випадкових чисел, повернутих Next(int maxValue) є упередженим

Є параметри, для яких Next(int maxValue)явно неоднорідність. Наприклад, якщо підрахувати, r.Next(1431655765) % 2ви отримаєте 0приблизно 2/3 зразків. (Зразок коду в кінці відповіді.)

Помилка 3: NextBytes()метод неефективний.

Вартість за байт NextBytes()приблизно така велика, як вартість формування цілочисельної вибірки Next(). З цього я підозрюю, що вони справді створюють один зразок на байт.

Краща реалізація, що використовує 3 байти з кожної вибірки, прискориться NextBytes()майже в 3 рази.

Завдяки цьому недолік Random.NextBytes()лише на 25% швидший, ніж System.Security.Cryptography.RNGCryptoServiceProvider.GetBytesна моїй машині (Win7, Core i3 2600MHz).

Я впевнений, що якщо хтось перевірить вихідний / декомпільований байт-код, він знайде ще більше недоліків, ніж я виявив за допомогою аналізу чорної скриньки.


Зразки коду

r.Next(0x55555555) % 2 є сильно упередженим:

Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
    int num = r.Next(0x55555555);
    int num2 = num % 2;
    hist[num2]++;
}
for(int i=0;i<mod;i++)
    Console.WriteLine(hist[i]);

Продуктивність:

byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();

// Random.NextBytes
for(int i=0;i<100000;i++)
{
    r.NextBytes(bytes);
}

//One sample per byte
for(int i=0;i<100000;i++)
{   
    for(int j=0;j<bytes.Length;j++)
      bytes[j]=(byte)r.Next();
}

//One sample per 3 bytes
for(int i=0;i<100000;i++)
{
    for(int j=0;j+2<bytes.Length;j+=3)
    {
        int num=r.Next();
        bytes[j+2]=(byte)(num>>16);   
        bytes[j+1]=(byte)(num>>8);
        bytes[j]=(byte)num;
    }
    //Yes I know I'm not handling the last few bytes, but that won't have a noticeable impact on performance
}

//Crypto
for(int i=0;i<100000;i++)
{
    cr.GetBytes(bytes);
}

1
Цікаво, я можу підтвердити ваші знахідки: на моїй машині Next (1431655765) також дається 2/3 з будь-яким посівом. У чому магія 1431655765? Як ви дійшли до цього номера?
citykid 02.03.14

1
@citykid Подивіться на число як шістнадцяткове або бітове. Це магія виникає через сумнівний спосіб Randomперетворення 31-бітового цілого числа в число із зазначеною верхньою межею. Я забув деталі, але це щось на зразок randomValue * max / 2^{31}.
CodesInChaos 03.03.14

1431655765_10 = 1010101010101010101010101010101_2
Тім С.

6
Хм Отже, яку реалізацію Random для C # ви рекомендуєте використовувати?
Arsen Zahray

1
Свята корова, нерівномірність розподілу Next(), продемонстрована вами тут, є досить вражаючою помилкою - і досі присутньою сьогодні, через 6 років після того, як ви вперше записали свої висновки. (Я кажу "помилка", а не просто "недолік", оскільки документи стверджують, що "псевдовипадкові числа вибираються з однаковою ймовірністю з кінцевого набору чисел" . Це не так, і ваш код тут це підтверджує.)
Mark Amery

24

System.Random набагато ефективніший, оскільки не генерує криптографічно захищених випадкових чисел.

Простий тест на моїй машині, який заповнює буфер у 4 байти випадковими даними 1 000 000 разів, займає 49 мс для Random, але 2845 мс для RNGCryptoServiceProvider. Зверніть увагу, що якщо ви збільшуєте розмір заповнюваного буфера, різниця звужується, оскільки накладні витрати для RNGCryptoServiceProvider менш важливі.


2
Дякуємо, що продемонстрували це за допомогою фактичного тесту.
Lernkurve

3
Ви можете подумати, що це суворо, але -1 для оприлюднення результатів тесту продуктивності без включення коду тесту. Навіть якщо характеристики продуктивності Randomта RNGCryptoServiceProviderне змінювались за останні 8 років (що, наскільки я знаю, вони могли б мати), я бачив достатньо повністю зламаних тестів, що використовуються в Stack Overflow, щоб не довіряти результатам тесту, код якого не є загальнодоступним.
Mark Amery

21

Найбільш очевидні причини вже були згадані, тож ось одна більш незрозуміла: криптографічні PRNG, як правило, повинні постійно пересіватися з "справжньою" ентропією. Таким чином, якщо ви використовуєте CPRNG занадто часто, ви можете вичерпати пул ентропії системи, який (залежно від реалізації CPRNG) або послабить його (таким чином дозволяючи зловмиснику передбачити його), або заблокує при спробі заповнити його пул ентропії (таким чином стаючи вектором атаки для DoS-атаки).

У будь-якому випадку, ваша програма зараз стала вектором атаки для інших, абсолютно не пов’язаних між собою програм, які - на відміну від ваших - насправді життєво залежать від криптографічних властивостей CPRNG.

Це справжня реальна проблема, до речі, яка спостерігалася на безголових серверах (які, природно, мають досить малі пули ентропії, оскільки їм бракує джерел ентропії, таких як введення миші та клавіатури) під управлінням Linux, де програми неправильно використовують /dev/randomядро CPRNG для всіх видів випадкових чисел, тоді як правильною поведінкою було б читати невелике значення насіння /dev/urandomта використовувати його для засівання власного PRNG.


Я читав статтю Вікіпедії та деякі інші Інтернет-джерела про ентропію та виснаження ентропії, і я не зовсім це розумію. Як я можу виснажувати пул ентропії, коли генератор випадкових чисел подається із системним часом, кількістю вільних байт тощо? Як інші можуть використовувати його як вектор атаки для прогнозування випадкових чисел? Чи можете ви навести простий приклад? Можливо, цю дискусію потрібно вимкнути з мережі. en.wikipedia.org/wiki/Entropy_%28computing%29
Lernkurve

3
Системний час не є джерелом ентропії, оскільки він передбачуваний. Я не впевнений у кількості вільних байтів, але я сумніваюся, що це також високоякісне джерело ентропії. Відправляючи більше запитів на сервер, зловмисник може спричинити зменшення кількості вільних байт, що робить його частково детермінованим. Ваше додаток стає вектором атаки, оскільки, вичерпуючи пул ентропії, воно змушує інше, критичне для безпеки додаток, використовувати менш випадкові випадкові числа - або чекати, поки джерело ентропії поповниться.
quant_dev

Я розумію, що якщо у когось є псевдовипадковий генератор, який живиться, наприклад, 32-бітовим насінням, атака грубої сили часто буде досить легкою; навіть 64-розрядне насіння може бути піддане атакам на день народження. Як тільки насіння стає набагато більшим за це, однак, я не зовсім бачу ризик. Якщо є випадковий генератор, який для кожного байту виводу приймає 128-розрядний стан через алгоритм блочного шифрування, а потім виводить 8 біт, як зловмисник може навіть зробити висновок про стан, маючи послідовні вихідні байти, відсутність слабких сторін сам алгоритм шифрування?
supercat

11

Якщо ви програмуєте онлайн-карту чи лотерею, тоді ви хочете переконатися, що послідовність майже неможливо вгадати. Однак, якщо ви показуєте користувачам, скажімо, цитата дня продуктивності важливіша за безпеку.


9

Це було дещо обговорено, але зрештою, питання продуктивності є другорядним фактором при виборі СПГ. Існує величезна кількість RNG, і консервована Lhmer LCG, з якої складається більшість системних RNG, не найкраща і навіть не найшвидша. У старих повільних системах це був чудовий компроміс. Цей компроміс рідко коли-небудь справді актуальний у наші дні. Річ зберігається в сучасних системах насамперед тому, що A) річ вже побудована, і в цьому випадку немає жодної реальної причини “винаходити колесо”, і B) для того, для чого переважна частина людей буде використовувати це, це 'досить добре'.

Зрештою, вибір РНГ зводиться до співвідношення ризик / винагорода. У деяких програмах, наприклад, у відеоіграх, немає жодного ризику. RNG Lehmer є більш ніж достатнім, він невеликий, лаконічний, швидкий, добре зрозумілий і "в коробці".

Якщо додатком є, наприклад, онлайн-гра в покер або лотерея, де задіяні фактичні призи, і в якийсь момент рівняння в гру вступають реальні гроші, "у полі" Лемер більше не підходить. У 32-розрядної версії він має лише 2 ^ 32 можливі допустимі стани, перш ніж починати цикл у кращому випадку . У наші дні це відкриті двері для нападу грубих сил. У такому випадку розробник захоче перейти на щось на зразок дуже довгого періоду СПГ деяких видів і, ймовірно, посіяти його у криптографічно сильного постачальника. Це дає хороший компроміс між швидкістю та безпекою. У такому випадку людина буде шукати щось на зразок Mersenne Twister або багаторазового рекурсивного генератора .

Якщо додаток - це щось на зразок передачі великої кількості фінансової інформації через мережу, то зараз існує величезний ризик, і він значно перевищує будь-яку можливу винагороду. Досі є броньовані машини, тому що іноді важкоозброєні чоловіки є єдиною безпекою, яка є адекватною, і повірте мені, якщо бригада спеціальних підрозділів з танками, винищувачами та вертольотами була фінансово можливою, це був би метод вибору. У такому випадку використання криптографічно міцного RNG має сенс, адже який би рівень безпеки ви не отримали, це не так багато, як ви хочете. Тож ви візьмете стільки, скільки зможете знайти, а вартість - це дуже, дуже віддалене питання, яке посідає друге місце, або в часі, або в грошах. І якщо це означає, що кожна випадкова послідовність займає 3 секунди для створення на дуже потужному комп’ютері, ви зачекаєте 3 секунди,


3
Я думаю, ви помиляєтесь щодо своїх величин; надсилання фінансових даних повинно бути надзвичайно швидким; якщо ваш торговий алгоритм може досягти результату на 0,1 мс швидше, ніж конкурент, ви потрапляєте краще в чергу на команди покупки / продажу / зупинки-втрати / котирування. 3 секунди - це вічність. Ось чому торговці інвестують у шалено хороші комп’ютери. Див. Попередню відповідь; Crypt.RNG займає лише 0,0028 мс на нове число; 0,0000028 секунди, тож ви вимикаєтеся на 9 порядків з точки зору того, скільки потрібно обробки, а також того, наскільки важлива швидкість.
Генрік

9

Зверніть увагу, що клас System.Random у C # кодований неправильно, тому його слід уникати.

https://connect.microsoft.com/VisualStudio/feedback/details/634761/system-random-serious-bug#tabs


... і, схоже, це ніколи не вдасться виправити.
Спендер

2
Здається, посилання недоступне, тому що Microsoft відмовився від "підключення".
MSeifert

4

Не всі потребують криптографічно захищених випадкових чисел, і вони могли б отримати більше користі від більш швидкого простого prng. Можливо, ще важливіше те, що ви можете керувати послідовністю для System.Random numbers.

У симуляції з використанням випадкових чисел, які ви можете відтворити, ви повторюєте імітацію з тим самим насінням. Це може бути зручно для відстеження помилок, коли ви також хочете поновити заданий несправний сценарій - запустити свою програму з точно такою ж послідовністю випадкових чисел, які призвели до збоїв програми.


2

Якщо мені не потрібна безпека, тобто я просто хочу відносно невизначене значення, а не криптографічно сильне, Random має набагато простіший інтерфейс для використання.


2

Різні потреби вимагають різних СПГ. Для криптографії ви хочете, щоб ваші випадкові числа були якомога випадковішими. Для моделювання в Монте-Карло ви хочете, щоб вони рівномірно заповнювали простір і мали можливість запускати RNG з відомого стану.


1
Якби тільки System.Random зробив будь-що .. о, добре.
користувач2864740

2

Random не є генератором випадкових чисел, це детермінований генератор псевдовипадкових послідовностей, який бере свою назву з історичних причин.

Причиною використання System.Randomє те, що ви хочете ці властивості, а саме детерміновану послідовність, яка гарантовано дасть однакову послідовність результатів при ініціалізації з тим самим насінням.

Якщо ви хочете покращити "випадковість", не жертвуючи інтерфейсом, ви можете успадкувати від System.Randomзаміни декількох методів.

Чому ви хочете детерміновану послідовність?

Однією з причин мати детерміновану послідовність, а не справжню випадковість, є її повторюваність.

Наприклад, якщо ви виконуєте числове моделювання, ви можете ініціалізувати послідовність (справжнім) випадковим числом і записати, яке число було використано .

Потім, якщо ви хочете повторити те саме моделювання, наприклад, для налагодження, ви можете зробити це, замість того, щоб ініціалізувати послідовність із записаним значенням.

Чому ви хочете саме цю, не дуже гарну послідовність?

Єдиною причиною, про яку я можу подумати, є зворотна сумісність із існуючим кодом, який використовує цей клас.

Коротше кажучи, якщо ви хочете покращити послідовність, не змінюючи решту коду, продовжуйте.


1

Я написав гру (Кришталеві повзунки на iPhone: Тут ), яка розмістила б на карті "випадкову" серію дорогоцінних каменів (зображень), і ви повернули б карту, як хотіли, і вибрали їх, і вони пішли. - Подібно до Bejeweled. Я використовував Random (), і він був засіяний кількістю 100ns галочок з моменту завантаження телефону, досить випадковим насінням.

Я знайшов це дивовижне що це дозволить створювати ігри, майже ідентичні одна одній - з 90 або близько того самоцвітів, двох кольорів, я отримав би ВІДНОСНО однаково, за винятком 1 до 3 дорогоцінних каменів! Якщо ви перекинете 90 монет і отримаєте однаковий шаблон, за винятком 1-3, це дуже малоймовірно! У мене є кілька знімків екрану, які показують їх однаково. Я був вражений тим, наскільки поганим був System.Random ()! Я припустив, що ПОВИНЕН писати щось жахливо неправильно у своєму коді і неправильно використовувати його. Хоча я помилився, це був генератор.

Як експеримент - і остаточне рішення, я повернувся до генератора випадкових чисел, який я використовую з 1985 року або близько того, - що НАСТІЛЬКО краще. Він швидший, має період 1,3 * 10 ^ 154 (2 ^ 521), перш ніж повториться. Оригінальний алгоритм був засіяний 16-бітовим числом, але я змінив його на 32-бітове число та покращив початкове засівання.

Оригінальний тут:

ftp://ftp.grnet.gr/pub/lang/algorithms/c/jpl-c/random.c

Протягом багатьох років я кидав усі тести на випадкові числа, про які я міг подумати, і минув усі. Я не очікую, що він має якесь значення як криптографічний, але він повертає число так швидко, як "return * p ++;" поки не закінчиться 521 біт, а потім він запускає швидкий процес над бітами, щоб створити нові випадкові.

Я створив обгортку C # - назвав її JPLRandom () реалізував той самий інтерфейс, що і Random (), і змінив усі місця, де я це назвав у коді.

Різниця була НАПОЛЬКО кращою - OMG, я був вражений - не повинно бути жодного способу, який я міг би визначити, просто подивившись на екрани близько 90-ти самоцвітів у зразку, але після цього я зробив екстрений випуск своєї гри.

І я ніколи більше ніколи не використовував би System.Random (). Я ШОКУВАНА, що їх версія здута чимось, якому зараз 30 років!

-Traderhut Games


3
Моє перше припущення - ви Randomзанадто часто відтворювались . Він повинен бути створений лише один раз, Nextколи багато разів викликає цей екземпляр. Randomце погано, але не , що погано. Чи можете ви опублікувати зразок програми разом із парою насіння, що демонструє цю проблему?
CodesInChaos

Код створив би Random () на початку кожного рівня (але це була велика проблема з рівнем 1 більше, ніж пізніші). Код був приблизно таким:
Traderhut Games

Rnd = новий Random ((uint) GameSeed); NextGameSeed = Rnd.Next (2000000000); Кожен рівень використовував новий Випадковий, який був створений з новим насінням - Насіння було збережено для кожного рівня, щоб я міг відтворити карту, а також підтвердити послідовність випадкових насіння, що відповідають. Це дозволяє мені підтвердити, що гра є дійсною серією карт, які були вирішені, і відтворити гру.
Ігри Traderhut

І спочатку Random було створено на основі System.DateTime.Now.Ticks (або 0), а потім GameSeed було вибрано, використовуючи той самий виклик, що і Rnd.Next () вище. Якщо я не можу цього зробити, то виникає серйозна проблема із засіванням генератора випадкових чисел.
Ігри Traderhut

це не відповідь на вихідне питання!
Mike Dinescu

-1

Оскільки System.Random базується тут за його "некоректність" та упередженість, я перевірив себе.

розподіл

Цей код f # демонструє, що він поводиться дуже добре - на моїй середній машині:

let r = System.Random()
Seq.init 1000000 (fun _ -> r.Next(0,10))
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.iter (printfn "%A")

(0, 100208)
(1, 99744)
(2, 99929)
(3, 99827)
(4, 100273)
(5, 100280)
(6, 100041)
(7, 100001)
(8, 100175)
(9, 99522)    

Версії Framework, машина, операційна система - все це може змінити ситуацію. Введіть код у F # interactive на вашому комп'ютері та спробуйте самі. Щодо цирптографії я читав

let arr = [| 0uy |]
let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0])
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.take 10 // show first 10 bytes
|> Seq.iter (printfn "%A")

// distribution of first 10 bytes
(0uy, 3862)
(1uy, 3888)
(2uy, 3921)
(3uy, 3926)
(4uy, 3948)
(5uy, 3889)
(6uy, 3922)
(7uy, 3797)
(8uy, 3861)
(9uy, 3874)

продуктивність

#time

let arr = [| 0uy |]

let r = System.Random()
Seq.init 1000000 (fun _ -> r.NextBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.204, CPU: 00:00:00.203, GC gen0: 45, gen1: 1, gen2: 1
val it : int64 = 127503467L

let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.365, CPU: 00:00:00.359, GC gen0: 44, gen1: 0, gen2: 0
val it : int64 = 127460809L

що передбачає співвідношення 1: 2 і дещо приємнішу поведінку пам’яті крипто-версії.

висновок

Перевагою є System.Random, головним чином за набагато приємніший API, дещо за продуктивність та непоганий розподіл. System.Random може також зменшити залежності бібліотеки, і якщо фреймворк перенесено, System.Random, ймовірно, буде доступний до варіанту Crypto.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.