|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Делаю так: Код: c# 1. 2. 3. 4. 5. 6.
Пока количество элементов = 2^24, всё работает. При 2^25 ловлю System.OutOfMemoryException. Если же звать конструктор без параметров Tested = new ConcurrentDictionary<int, bool>(); то Exception не ловится, а просто приложение "stop working". В обоих случаях всё происходит в момент выделения процессу памяти ~1400000 кб. Вопрос. Есть ли ограничения на максимальное кол-во записей в ConcurrentDictionary, либо на размер выделенной под него памяти? Либо имеет значение только общий размер памяти, выделенной 32-битному процессу? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 13:18 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Небольшое уточнение: Exception ловится в момент заполнения словаря, после работы конструктора. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 13:34 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Это проблема 32-битного процесса. Всего 4 Гб из них 2 Гб ОС, вторые 2 Гб проге, в них и .Net и твои данные. В твоем случае лучше BitArray взять. Тут будет 1 бит - одно значение, т.е. все положительные значения Int32 (до 2^31) займут 256 Мб (2^28) ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 13:41 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Я бы взял BitArray, но он не потокобезопасен. В моём случае без вариантов подходит только что-то из System.Collections.Concurrent Самое забавное в моей истории, что на 32-битной Windows 7 с 4 Гб ОЗУ иногда эта программа проходит описанную инициализацию и начинает работать, а на 64-битной Windows Server c большим количеством памяти устойчиво падает вышеописанным образом. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 13:51 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®Я бы взял BitArray, но он не потокобезопасен. Используй блокировки lock() . Быстрее будет чем с ConcurrentDictionary ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 14:02 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Если еще быстрее надо, то взять массив Int32[], прописать логику работы с битами, а для чтения/записи использовать Interlocked функции. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 14:07 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Пока в порядке эксперимента переписал всё под BitArray, работает правильно как с ConcurrentDictionary без принятия специальных мер по блокировке. Что очень интересно, если вспомнить что с обычным массивом (в самой первоначальной версии программы) были чудеса. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 14:48 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®работает правильно как с ConcurrentDictionary без принятия специальных мер по блокировке. Это твое "правильно" те еще грабли. Когда проблемы возникнут - исключений не будет, просто получишь неправильный результат своего расчета. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 14:52 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima T, ну, если задача чисто заполнить справочник и он уверен в том, что пересечений из разных потоков не будет, то по сути всё отработает без ошибок. Но это же бессмысленный пример в вакууме :) одним заполнением то, он не ограничится (наверное) ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 15:01 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Т.к. работа с битами происходит через байты, то вполне возможна такая ситуация когда два потока одномоментно захотят установить разные биты в одном байте. Например это может произойти так Поток 1Поток 2Прочитал байтПрочитал байтУстановил бит 3Установил бит 5Записал байтЗаписал байт в итоге то что сделал Поток 1 будет затерто, т.е. бит 3 не будет установлен. Поэтому блокировки доступа при записи обязательны. При чтении можно не блокировать доступ, но тогда перед записью, внутри блокировки делать повторное чтение. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 15:21 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima TЭто твое "правильно" те еще грабли. Всецело догадываюсь об этом и обещаю заблаговременно принять меры :) А пока факт остаётся фактом: BitArray работает правильно там, где bool[] вынудил прибегнуть к ConcurrentDictionary, при числе потоков от 4 до 32. Прироста скорости по сравнению с ConcurrentDictionary пока не обнаружил. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 15:22 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®bool[] вынудил прибегнуть к ConcurrentDictionary, при числе потоков от 4 до 32. bool[] ничем не отличается от BitArray, разве что в 8 раз больше места требуется. AR®Прироста скорости по сравнению с ConcurrentDictionary пока не обнаружил. Можно не заметить если на работу с массивом уходит незначительная часть времени работы проги. Например если это 1%, то даже если в 10 раз ускорилось, то ускорение всего 0,9% от общего времени. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 15:35 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima Tbool[] ничем не отличается от BitArray, разве что в 8 раз больше места требуется. Был бы готов согласиться, но эксперимент выявил обратное. Dima TМожно не заметить если на работу с массивом уходит незначительная часть времени работы Вполне допускаю. Примерно так оно в этой программе и есть. Огорчает другое: при 2^25 элементов процесс запустился, а при 2^26 - уже нет. Буду думать... ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 16:03 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Похоже, теперь дохнет уже на выделении памяти объектам в каждом потоке. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 16:11 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima T Благодарю за "наводку" на класс BitArray. Скажите, будет ли в общем случае достаточно брать в lock(){ } операции записи в массив? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 17:35 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®Скажите, будет ли в общем случае достаточно брать в lock(){ } операции записи в массив? Думаю да, но на 100% не уверен. Лучше все обращения обернуть. Сделай класс-обертку, два метода Read() и Write(). В них пропиши c lock(). Как понял на общем времени работы твоего кода это особо не скажется, но надежность будет гарантированная. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.05.2016, 18:02 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
По крайней мере размер требуемой памяти в этом случае оцинеть не сложно, так что рекомендую использовать MemoryFailPoint и ловить InsufficientMemoryException. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 08:02 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®Скажите, будет ли в общем случае достаточно брать в lock(){ } операции записи в массив? Посмотрел исходник bitarray.cs Чтение Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
Думаю без lock() можно читать. Нечему тут глючить при многопоточности. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 08:41 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Предварительный диагноз такой: с BitArray немного быстрее, чем с ConcurrentDictionary, но только пока не использую lock(){}. С lock остаётся только преимущество в памяти (что для моего случая важно). Видимо потому, что блокировка накладывается на весь массив, а не на отдельный бит :) Интересно, а можно ли скомпилировать 64-битное приложение на 32-битном компе? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 12:56 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®С lock остаётся только преимущество в памяти (что для моего случая важно). Видимо потому, что блокировка накладывается на весь массив, а не на отдельный бит :) Блокировка вообще не накладывается. Это просто флаг, первый поток установил и что-то делает, второй, при попытке его установить - останавливается и ждет пока первый не снимет. Можешь разделить массив на условные блоки (0-1048575, 1048576-... и т.д.) и использовать отдельный объект для блокировки каждого блока. Только учти что блоки массива, за который отвечает одна блокировка, должны быть кратны 32. Т.к. внутри BitArray используется Int32[]. AR®Интересно, а можно ли скомпилировать 64-битное приложение на 32-битном компе? Скомпилировать можно, но оно не запустится. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 13:10 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima TСкомпилировать можно, но оно не запустится. Не запустится на компьютере компиляции - это устраивает. Хотелось бы, чтобы оно запустилось на 64-битной ОС, где памяти стоит побольше, и не будет ограничения как для 32-битного процесса. Никогда не делал так, потому спрашиваю. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 13:46 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®С lock остаётся только преимущество в памяти (что для моего случая важно). Видимо потому, что блокировка накладывается на весь массив, а не на отдельный бит :) Можно Interlocked.CompareExchange() вместо lock(). Так вообще без блокировок. Только класс придется свой делать. class ConcurrentBitArrayСкопипастил из BitArray только минимально нужное. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41.
AR®Хотелось бы, чтобы оно запустилось на 64-битной ОС, где памяти стоит побольше, и не будет ограничения как для 32-битного процесса. Если по-простому: Внутри EXE находится IL-код, по месту запуска он может заработать и как х32 и как x64 без перекомпиляций. Можно явно задать чтобы везде одинаково было. Это в заголовке EXE указывается. Подробно у Рихтера расписано. Как в студии настроить не знаю, а с командной строки так компилировать Код: c# 1.
без указания платформы, тогда на x32 компе запустится как x32, на x64 как x64 Только не надейся что при x64 у тебя не выскочит OutOfMemory. Там тоже ограничения есть, виндовс как-то ограничивает чтобы приложение всю память не отъело. И еще такой момент: x64 работает на ~30% медленнее чем х32. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 14:38 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Спасибо за класс. Dima TТолько не надейся что при x64 у тебя не выскочит OutOfMemory. Там тоже ограничения есть, виндовс как-то ограничивает чтобы приложение всю память не отъело. Очень интересно, каковы они и где установливаются. Работает же как-то, ну например, SQL Server, который берёт, сколько ему нужно. Dima TИ еще такой момент: x64 работает на ~30% медленнее чем х32. Это с лихвой компенсировалось бы отсутствием ограничений на выделяемую процессу память. В процессе экспериментов я попутно выяснил, что, например, BitArray даёт время работы раза ~в 4 больше, чем bool[ ] (он используется у меня в каждом отдельном потоке). И вот ещё интересный вопрос. Если делать свой класс, как ваш ConcurrentBitArray, с точки зрения минимизации времени работы, что лучше взять за основу: Int32, или более короткие Int16, byte, или наоборот, длинный Int64 ? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 14:56 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
AR®Спасибо за класс. Dima TТолько не надейся что при x64 у тебя не выскочит OutOfMemory. Там тоже ограничения есть, виндовс как-то ограничивает чтобы приложение всю память не отъело. Очень интересно, каковы они и где установливаются. Работает же как-то, ну например, SQL Server, который берёт, сколько ему нужно. Специально не интересовался, случайно нигде не попадалось, так что гугл в помощь если интересно. Наверно есть какое-нибудь WinAPI чтобы попросить ОС дать больше чем по умолчанию. AR®Dima TИ еще такой момент: x64 работает на ~30% медленнее чем х32. Это с лихвой компенсировалось бы отсутствием ограничений на выделяемую процессу память. В процессе экспериментов я попутно выяснил, что, например, BitArray даёт время работы раза ~в 4 больше, чем bool[ ] (он используется у меня в каждом отдельном потоке). bool[ ] быстрее, т.к. там просто получение байта из массива (m_array[index]), без всяких доп.расчетов (m_array[index / 32] & (1 << (index % 32))) AR®И вот ещё интересный вопрос. Если делать свой класс, как ваш ConcurrentBitArray, с точки зрения минимизации времени работы, что лучше взять за основу: Int32, или более короткие Int16, byte, или наоборот, длинный Int64 ? Int16 и byte отпадают Interlocked.CompareExchange() перегружен только для Int32 и Int64. Работа с Int64 под x32 медленнее. В принципе можешь затестить как оно будет в твоей задаче. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 15:18 |
|
Максимальный размер ConcurrentDictionary в 32-битных приложениях
|
|||
---|---|---|---|
#18+
Dima TInt16 и byte отпадают Interlocked.CompareExchange() перегружен только для Int32 и Int64 Я имел ввиду, что если городить совсем свой огород и не закладываться на использование Interlocked, в каком случае обращение к требуемому биту будет быстрее: с byte, Int16, Int32, Int64? И ещё: byte и Int16 будут занимать в памяти в случае большого массива из них действительно байт и 2 соответственно? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.05.2016, 15:44 |
|
|
start [/forum/topic.php?fid=20&msg=39244107&tid=1399876]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
157ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 276ms |
0 / 0 |