Как оптимизировать подкачку для большой базы данных в памяти - PullRequest
7 голосов
/ 07 июня 2010

У меня есть приложение, в котором вся база данных реализована в памяти с использованием stl-map для каждой таблицы в базе данных.

Каждый элемент в карте stl является сложным объектом со ссылками на другие элементы в других картах stl.

Приложение работает с большим объемом данных, поэтому оно использует более 500 МБ ОЗУ. Клиенты могут связаться с приложением и получить отфильтрованную версию всей базы данных. Это делается путем прогона всей базы данных и поиска элементов, относящихся к клиенту.

Когда приложение работает в течение часа или около того, Windows 2003 SP2 начинает распаковывать части оперативной памяти для приложения (даже если на компьютере установлено 16 ГБ ОЗУ).

После того, как приложение было частично выгружено, вход клиента в систему занимает много времени (10 минут), поскольку теперь он генерирует ошибку страницы для каждого поиска указателя в stl-map. Если клиент снова выполняет вход в систему сразу после этого, он выполняется быстро (несколько секунд), поскольку вся память теперь снова находится в ОЗУ.

Я вижу, что Windows может заблокировать память в ОЗУ, но это обычно рекомендуется только для драйверов устройств и только для "небольших" объемов памяти.

Я полагаю, что плохим решением может быть перебрать всю базу данных памяти и, таким образом, сказать Windows, что мы все еще заинтересованы в хранении модели данных в ОЗУ.

Полагаю, еще одно плохое решение - полностью отключить файл подкачки в Windows.

Я полагаю, что дорогостоящим решением будет база данных SQL, а затем переписать все приложение, чтобы использовать слой базы данных. Тогда, надеюсь, в системе баз данных будут реализованы средства для быстрого доступа.

Существуют ли другие более элегантные решения?

Ответы [ 6 ]

5 голосов
/ 07 июня 2010

Это звучит как утечка памяти или серьезная проблема фрагментации.Мне кажется, что первым шагом было бы выяснить, что заставляет 500 МБ данных использовать 16 ГБ ОЗУ и все еще требовать большего.

Редактировать: в Windows есть триммер рабочего набора, который активно пытается просматривать страницыбездействующие данные.Основная идея состоит в том, что он просматривает и помечает страницы как доступные, но оставляет данные в них (и менеджер виртуальной памяти знает, какие данные в них находятся).Однако если вы попытаетесь получить доступ к этой памяти до того, как она будет выделена для других целей, она будет помечена как снова используемая, что, как правило, не позволит ее выгружать.

Если вы действительно считаете, чтоисточник вашей проблемы, вы можете косвенно управлять триммером рабочего набора, вызывая SetProcessWorkingSetSize.По крайней мере, по моему опыту, это очень редко полезно, но вы можете оказаться в одной из тех необычных ситуаций, где это действительно полезно.

2 голосов
/ 07 июня 2010

Как сказал @Джерри Коффин, действительно похоже, что ваша настоящая проблема - утечка памяти. Исправьте это.

Но, к сведению, ни одно из ваших "решений для бедняков" не сработает. На всех.

Windows выводит на экран некоторые из ваших данных , потому что в RAM нет места для этого . Цикл по всей базе данных памяти будет загружать каждый байт модели данных, да ... что приведет к тому, что другие его части будут выгружены. В конце концов, вы сгенерируете много сбоев страниц, и единственное отличие в конце будет , из которого части структуры данных будут разбиты на страницы.

Отключение файла подкачки? Да, если вы думаете, что тяжелый сбой лучше, чем низкая производительность. Windows не выводит данные, потому что это весело. Это делает это для обработки ситуаций, когда в противном случае не хватило бы памяти. Если вы отключите файл подкачки, приложение просто рухнет, если в противном случае данные будут выгружены.

Если ваш набор данных действительно настолько большой, что не помещается в памяти, тогда я не понимаю, почему база данных SQL будет особенно "дорогой". В отличие от вашего текущего решения, базы данных оптимизированы для этой цели. Они предназначены для обработки наборов данных, слишком больших для размещения в памяти, и для эффективного выполнения этого.

Похоже, у вас утечка памяти. Исправление, которое было бы изящным, эффективным и правильным решением.

Если вы не можете этого сделать, то либо

  • добавьте больше оперативной памяти при проблеме (приложение в конечном итоге использует 16 ГБ? Добавьте 32 или 64 ГБ в него) или
  • переключиться на формат, оптимизированный для эффективного доступа к диску (возможно, база данных SQL)
0 голосов
/ 07 июня 2010

Я могу поверить, что это ошибка некорректного поведения файла подкачки - я запускал свои ноутбуки в основном с отключенным подкачкой, начиная с nt4.0. По моему опыту, по крайней мере до XP Pro, Windows навязчиво обменивается страницами, чтобы обеспечить сомнительное преимущество действительно очень медленного расширения максимального пространства рабочего набора.

Спросите, какую выгоду дает обмен жестким диском с 16 гигабитами реальной доступной оперативной памяти? Если ваш рабочий набор настолько велик, что для него требуется больше виртуальной памяти, чем +10 Гигабайт, то после того, как свопинг действительно необходим, процессам потребуется чуть больше, а в тысячи раз дольше. В Windows неукротимый кэш файловой системы, кажется, противоречит отношениям.

Теперь, когда у меня (очень) время от времени заканчивается рабочий набор на моих ноутбуках с XP, пробок нет, виновное приложение просто вылетает. Утилита, которая приостанавливает процессы склеивания памяти до этого времени и делает предупреждение, было бы неплохо, но нет такой вещи, как нарушение, сбой, а иногда и explorer.exe тоже выходит из строя.

Pagefiles - кому они нужны

0 голосов
/ 07 июня 2010

У меня есть приложение, в котором вся база данных реализована в памяти с использованием stl-map для каждой таблицы в базе данных.

Это начало конца: STL's std ::карта крайне неэффективна в памяти.То же самое относится к std :: list.Каждый элемент будет выделяться отдельно, вызывая довольно серьезные потери памяти.Я часто использую std :: vector + sort () + find () вместо std :: map в приложениях, где это возможно (больше поисков, чем модификаций), и я заранее знаю, что использование памяти может стать проблемой.

Когда приложение работает в течение часа или около того, Windows 2003 SP2 начинает распаковывать части оперативной памяти для приложения (даже если на компьютере установлено 16 ГБ ОЗУ).

Трудно сказать, не зная, как написано ваше заявление.В Windows есть возможность выгружать из ОЗУ любую память из неактивных приложений.Но это обычно влияет на файлы, отображаемые в память, и тому подобное.

В противном случае, я бы настоятельно рекомендовал прочитать документацию по управлению памятью Windows .Это не очень легко понять, но в Windows есть все виды и типы памяти, доступные приложениям.Мне никогда не везло с этим, но, вероятно, в вашем приложении будет работать пользовательский std :: allocator.

0 голосов
/ 07 июня 2010

У нас похожая проблема, и решение, которое мы выбрали, состояло в том, чтобы выделить все в блоке общей памяти.AFAIK, Windows не выкладывает это.Тем не менее, использование stl-map здесь не для слабонервных и было выше того, что нам требовалось.

Мы используем Boost Shared Memory , чтобы реализовать это для нас, и это работает хорошо.Внимательно следуйте примерам, и вы быстро заработаете.Boost также имеет Boost.MultiIndex , который будет делать то, что вы хотите.

Для бесплатного решения sql вы рассматривали Sqlite ?У них есть возможность работать в качестве базы данных в памяти.

Удачи, звучит как интересное приложение.

0 голосов
/ 07 июня 2010

---- Редактировать

Принимая во внимание объяснение змеиной стопы, проблема заключается в замене памяти, которая не используется в течение более длительного периода времени, и из-за этого при отсутствии данных в памяти при необходимости. Это так же, как это:

Могу ли я сказать Windows не выгружать память определенного процесса?

и функция VirtualLock должна выполнить свою работу:

http://msdn.microsoft.com/en-us/library/aa366895(VS.85).aspx

---- Предыдущий ответ

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

Если у вас есть утечка памяти, то было бы больше усилий преобразовать все приложение в SQL, чем отлаживать приложение.

SQL не может быть быстрее хорошо спроектированной доменной базы данных в памяти, и если у вас есть ошибки, скорее всего, у вас будут и другие в версии SQL.

Если это проблема с памятью, вам все равно придется переключиться на SQL, и это звучит как хороший момент.

...