metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2009-03-23 09:57 am

Забавный баг

Третий день ловлю баг, связанный с тем, что TCP сервер под большой нагрузкой падает с ошибкой out of memory, хотя ему выделено всего 800 мег и еще гиг физической памяти свободно. На каждое воспроизведение бага - сутки работы сервера под нагрузкой в несколько раз больше рабочей.

Оказалось - нехватка виртуальной памяти, причем вообще - не самой памяти, а ее адресного пространства. Менеджер памяти при выделении/удалении сильно фрагментирует память, в итоге адресам становится мало 2^31 и все падает, с ошибками типа "not enough storage" в самых левых функциях вроде записи в инишник.
Причем, западло в том, что увидеть это число в Task Manager нельзя, нужно смотреть Process Explorer или делать лог perfmon-ом.

[identity profile] aamonster.livejournal.com 2009-03-23 08:06 am (UTC)(link)
Ничего забавного...
Вот в том числе из-за таких вещей и возникает желание переходить на .net.

[identity profile] metaclass.livejournal.com 2009-03-23 08:12 am (UTC)(link)
Ну да, есть вероятность, что тут их сборщик мусора бы как минимум дефрагментировал бы память. Очистить бы не очистил - это не забытые объекты, рабочие, просто расположены как попало.

[identity profile] aamonster.livejournal.com 2009-03-23 08:28 am (UTC)(link)
Угу.
Еще можно перейти на какую-нибудь альтернативную кучу типа quickheap - который жрет больше памяти, зато лишен упомянутого недостатка, а по эффективности кроет стандартные реализации, как бык овцу (http://rsdn.ru/article/dotnet/GCnet.xml#EPD)
(deleted comment)

[identity profile] bigfrogg.livejournal.com 2009-03-23 09:17 am (UTC)(link)
Вы пишите программы под win mobile которым не хватает двух гигабайт адресного пространства?
(deleted comment)

[identity profile] zamotivator.livejournal.com 2009-03-25 10:11 am (UTC)(link)
boost::memory_pool

[identity profile] thundertoad.livejournal.com 2009-03-23 08:44 am (UTC)(link)
наверное, лучший, но геморройный метод - собственный memory manager

[identity profile] thundertoad.livejournal.com 2009-03-23 10:02 am (UTC)(link)
ну с таким исследованием спорить глупо. но наш application-specific себя вполне оправдал. specific - несколько тысяч аллокаций в секунду.

[identity profile] lionet.livejournal.com 2009-03-23 11:01 am (UTC)(link)
Несколько тысяч - это копейки. Несколько миллионов в секунду - это делают современные аллокаторы на современных тачках.

[identity profile] thundertoad.livejournal.com 2009-03-23 08:34 pm (UTC)(link)
приношу извинения, протормозил. специально уточнил - у нас до трех миллонов в секунду. с тысячами не было бы этих проблем.

[identity profile] zamotivator.livejournal.com 2009-03-25 10:12 am (UTC)(link)
А зачем столько? оО

[identity profile] lionet.livejournal.com 2009-03-25 10:34 am (UTC)(link)
Не все умеют без аллокаций памяти работать с динамическими данными. Иногда проще классик инстанциировать на хипе, или там строчку аллоцировать.

[identity profile] bigfrogg.livejournal.com 2009-03-23 09:00 am (UTC)(link)
По моему наиболее просто задача решается переходом на x86-64. (Если заказчик программы такое допускает)

[identity profile] metaclass.livejournal.com 2009-03-23 09:10 am (UTC)(link)
Для заказчиков с такой нагрузкой можно было бы, но мой компилятор 64 бита не поддерживает.

[identity profile] bigfrogg.livejournal.com 2009-03-23 09:12 am (UTC)(link)
Значит самый просто способ - переписать программу так что бы она статически выделаля память сразу и много..

[identity profile] metaclass.livejournal.com 2009-03-23 09:23 am (UTC)(link)
Да, это практически и есть кастомный аллокатор для некоторых классов.

[identity profile] potan.livejournal.com 2009-03-23 09:45 am (UTC)(link)
Частично.
Фрагментация памяти создает много частично заполненых страниц и свопинг начнется раньше. А если учесть и то, что размер указателя вырос, то программа может потребовать значительно больше памяти.

[identity profile] bigfrogg.livejournal.com 2009-03-23 09:52 am (UTC)(link)
Ну у метакалса не хватает не пямти, памяти как раз он сказал есть ещё гиг. А с современными ценами на память, день работы программиста стоит как 8 гиг озу.
Значительно памяти больше программа не потребует. Даже если предпложить что вся программа состоит только из указателей, то памяти будет тратить всего в 2 раза больше, что совсем не много.

[identity profile] potan.livejournal.com 2009-03-23 10:23 am (UTC)(link)
Ну да, по этому частично решает.
А цену рабочего дня программиста надо сравнивать с ценой памяти, помноженной на количество пользователей...

[identity profile] metaclass.livejournal.com 2009-03-23 10:45 am (UTC)(link)
Оптимизировать нельзя - если сервер не будет требовать пару гиг памяти, это неэнтерпрайзно, клиенты не поймут, за что они платили :)

[identity profile] potan.livejournal.com 2009-03-23 10:56 am (UTC)(link)
Еще один повод отказаться от язвков класса C :-).

[identity profile] lionet.livejournal.com 2009-03-23 09:10 am (UTC)(link)
Erlang, Erlang.

[identity profile] potan.livejournal.com 2009-03-23 09:46 am (UTC)(link)
Да, там эта проблема хорошо решается.
Похоже, она типична для телекома...

[identity profile] lionet.livejournal.com 2009-03-23 11:02 am (UTC)(link)
В Эрланге нет фрагментации на строках разной длины. В Java есть.

[identity profile] volodymir-k.livejournal.com 2009-03-26 06:01 pm (UTC)(link)
Что такое "фрагментация" для copying garbage collector?

[identity profile] lionet.livejournal.com 2009-03-26 06:05 pm (UTC)(link)
согласен, спорол чушь.

[identity profile] eu3eu.livejournal.com 2009-03-23 09:45 am (UTC)(link)
А нефиг большие объекты в памяти держать. Временные файлы для того придуманы. Причём, не факт, что они реально на диске создаются - иногда они из кэша не успевают вылиться, как уже прибиваются, так что быстродействие не страдает.

[identity profile] metaclass.livejournal.com 2009-03-23 09:54 am (UTC)(link)
Большие объекты как раз нормально работают, в дыры от них потом мелкие селятся. А вот мелкие уже потом фрагментируют это дело вдоль и поперек.
Это реалтаймовый сервер сбора данных, там вся идея именно в том, чтобы держать в памяти множество мелких объектов, чтобы не грузить их из СУБД каждый раз. Но вообще там есть недоработка в этом кэше (лишние объекты лежат в памяти слишком долго), которую можно исправить, но это усложнит код и потребует в очередной раз прогонять все тестирование вдоль и поперек

[identity profile] lupus-lupusum.livejournal.com 2009-03-23 12:36 pm (UTC)(link)
смешной баг какой, сутки работы говоришь
интересно, можно ли его, или подобный, раньше чем за сутки обнаруживать - вроде можно, нет?


[identity profile] metaclass.livejournal.com 2009-03-23 01:18 pm (UTC)(link)
Можно, да. Отключить часть длительных операций и ускорить подачу данных для засирания мозга серверу.

[identity profile] nekhill.livejournal.com 2009-03-23 01:10 pm (UTC)(link)
Вот буквально пару дней назад видел в чужой наколенной реализации класса больших целых чисел подобную же проблему.
Всё хорошо работало до тех пор, пока люди не написали алгоритм, который в своей работе использует числа порядка двойки в степени 5033164800 (600*1024*1024*8). На такие числа этот наколенный класс пытается выделить непрерывный кусок памяти объёмом в 600 мегабайт, что ему, естественным образом, удаётся не всегда. Язык - C++. К счастью, проблема стала очевидной, когда в отладчике увидели падение на строке new unsigned int[digitsCount] и посмотрели, чему равен digitsCount.

[identity profile] thesz.livejournal.com 2009-03-23 09:23 pm (UTC)(link)
Да уж, куда как забавен. ;)

[identity profile] thesz.livejournal.com 2009-03-23 09:32 pm (UTC)(link)
Кстати, арены могут помочь.

Наверное. ;)