LINUX.ORG.RU

Проблемы с памятью


0

0

Ситуация.
Есть 2 потока.
Один постоянно читает данные и заполняет однонаправленный список.
Второй считывает эти данные, пишет их в БД, а затем освобождает память от прочитанных элементов.
При достижении определённой скорости заполнения списка, второй поток не успевает освободить память. Что в конечном итоге приводит к полному её заполнению.
Как можно решить сложившуюся ситуацию?

★★★★★

Никак. Если генерится больше данных, чем БД успевает принять, нужно часть данных выкидывать.

tailgunner ★★★★★
()
Ответ на: комментарий от UVV

>Там в удалённых у меня есть глупое предположение... =)

не. еще получишь проблемы с блокировкой БД. может стоит попробовать писать пачками?

вообще, стоит погуглить по оптимизации работы с конкретной СУБД.

generatorglukoff ★★
()
Ответ на: комментарий от UVV

> Там в удалённых у меня есть глупое предположение... =)

Аноксемиан прав. Если хочешь ускорить запись - попробуй пакетизировать операции записи. Вряд ли 2 нити что-то ускорят, если затык - в БД.

tailgunner ★★★★★
()

> Как можно решить сложившуюся ситуацию?
Тормозить первый поток, пока второй не справится с записью текущих данных.

gaa ★★
()
Ответ на: комментарий от gaa

> Тормозить первый поток, пока второй не справится с записью текущих данных.
Не вариант.

UVV ★★★★★
() автор топика

либо временно приостанавливать первый поток (тормозить), но это "не вариант"...

либо ускорять работу второго. А это можно добиться только оптимизацией работы второго с БД

samson ★★
()

1. Не освобождать память - выделять сразу большой буфер и использовать его (возможно цуклически) - это позволит снизить расходы на выделение/освобождение/дефрагментацию памяти. 2. Если второй поток по прежнему не будет успевать принимать данные (БД - узкое место и вся возможная оптимизация в БД уже сделана - удалены лишние индексы, партиционировано или добавлены диски в RAID) - то полученные данные нужно аггрегировать, т.е. суммировать в более крупные пакеты данных.

anonymous
()
Ответ на: комментарий от UVV

>> Тормозить первый поток, пока второй не справится с записью текущих данных. >Не вариант.

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

Absurd ★★★
()
Ответ на: комментарий от anonymous

>БД - узкое место и вся возможная оптимизация в БД уже сделана - удалены лишние индексы, партиционировано или добавлены диски в RAID

Есть еще Advanced Queues в Oraclе (например), можно субмитить джобы туда и репортиться о завершении работы асинхронным образом.

Absurd ★★★
()

1. Написать/заюзать аллокатор а-ля SLAB для работы с однотипными структурами.

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

3. В совсем плохой ситуации сбрасывать неуспевшие данные на диск в бэклог, потом при простое доставать потихоньку. Но тут всё зависит от типа данных и от задач.

mv ★★★★★
()

если база не справляется - юзай более быстрое решение: например berkeley db (http://www.oracle.com/technology/products/berkeley-db/index.html).

Что-то типа:

1. поток A получает данные складывает в небольшой буфер
2. поток B читает данные с буфера и пишет данные в bdb
3. поток C - читает данные с bdb, пишет в базу и удаляет с bdb

stpg
()
Ответ на: комментарий от stpg

> 3. поток C - читает данные с bdb, пишет в базу и удаляет с bdb

это может быть отдельным демоном.

stpg
()

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

Но, может, дело не в скорости, а в фрагментации памяти? Либсишный маллок весьма склонен.

Разумно свой аллокатор сделать: если данные все одного размера, то это сильно ускорит работу, а если порцайки разные, то скорее всего дело во фрагментации памяти, а не в скорости работы.

Если скорость генерации данных меняется туды-сюды, можно попробовать сделать компрессию (zlibom, например) или спасать список на диск -- при грамотной буферизации не так, чтобы шибко тормозить будет, оно ж строго линейно -- только тогда неплохо бы сбрасывать промежуточные данные на другой диск, не тот, где БД сидит.

Die-Hard ★★★★★
()
Ответ на: комментарий от stpg

> более быстрое решение: например berkeley db

Глупо! Зачем для промежуточного хранения строго линейного списка использовать хэш? Просто несколько файлов циклически переписывать, с подходящей буферизацией.

Кстати, любителям хешей рекомендую относительно недавнюю очень вкусную штуку, Токио кабинет называется: http://sourceforge.net/projects/tokyocabinet/

Die-Hard ★★★★★
()
Ответ на: комментарий от alex_custov

> Caché ?

ну да, на винчаке. bdb - очень быстрый;)

ещё с той же bdb помогает сортировака данных перед записью (чтоб cache-hit увеличить). но в данном случае ключи будут линейно ложиться - так что сортировка не требуется.

stpg
()
Ответ на: комментарий от Die-Hard

> Глупо! Зачем для промежуточного хранения строго линейного списка использовать хэш? Просто несколько файлов циклически переписывать, с подходящей буферизацией.

Логирование с возможностью восстановить не записанные данные?

Там есть кроме хеша ещё и очередь (Queue или Recno). Но сам их никогда не использовал.

stpg
()

Как бы то банально не звучало, своп + диета.

balodja ★★★
()
Ответ на: комментарий от stpg

> Логирование с возможностью восстановить не записанные данные?

Ещё раз -- то, что ты предлагаешь, глупость.

> Там есть кроме хеша ещё и очередь (Queue или Recno). Но сам их никогда не использовал.

Подумай, прошу! Очередь УЖЕ есть в условиях задачи!

То, что ты предлагаешь, примерно как вместо массива использовать хэш с навороченными транзакциями. По условию задачи _уже_ имеется линейный упорядоченный список. Ты предлагаешь "свести задачу к уже решённой", не подозревая, видимо, что "уже решённая задача" на порядки сложнее того, что надо решить...

Исходная задача. Дано: чайник, спички, газ, вода. Задача: вскипятить воду. Решение: зажечь газ, наполнить чайник водой, поставить его на огонь.

Усложняем задачу. Дано: наполненный водой чайник, зажженный газ. Цель - та же. Решение: вылить воду, погасить газ, таким образом мы приходим к условиям предыдущей задачи, решение которой уже известно.

:-(

Die-Hard ★★★★★
()
Ответ на: комментарий от stpg

>> Caché ?

> ну да, на винчаке. bdb - очень быстрый;)

Н-да...

Ты понимаешь хоть, что hash и cache -- разные слова?

Кстати, bdb - отнюдь не самый быстрый из хэшей. Он наиболее "навороченный", но т.н. "константные" хэши, например, в разы быстрее. Я выше ссылку привел, почитай про Токио Кабинет -- он на сегодня один из самых шустрых универсальных хэшей.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Подумай, прошу! Очередь УЖЕ есть в условиях задачи!

> То, что ты предлагаешь, примерно как вместо массива использовать хэш с навороченными транзакциями. По условию задачи _уже_ имеется линейный упорядоченный список. Ты предлагаешь "свести задачу к уже решённой", не подозревая, видимо, что "уже решённая задача" на порядки сложнее того, что надо решить...

Очередь есть, но она в памяти (и памяти не хватает). То, что я предложил - сделать очередь на диске. Но чтоб не изобретать велосипед - использовать уже готовое решение "например bdb". Что не так? Чем метод плох?

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

stpg
()
Ответ на: комментарий от Die-Hard

> Ты понимаешь хоть, что hash и cache -- разные слова?

Ну да я неправильно выразился. Кидайте в меня камнями;)

> Кстати, bdb - отнюдь не самый быстрый из хэшей. Он наиболее "навороченный", но т.н. "константные" хэши, например, в разы быстрее. Я выше ссылку привел, почитай про Токио Кабинет -- он на сегодня один из самых шустрых универсальных хэшей.

IIRC - константные хеши разделяют работу на 2 фазы - записть, а потом чтение. Очередь на константных хешах будет сделать тяжелее - так как придется держать аж два буфера одновременно - один на запись, второй на чтение;)

stpg
()
Ответ на: комментарий от mv

> Могу (за деньги) собрать под Этч свежайшую libastral из Fedora rawhide.

Чтобы меня тоже глючило, я предлагал дефрагментировать хип, зайти в какой-то кабинет в Токио, и путал хэш с кэшем? Не, я подожду стабильной версии в Дебильяне.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Чтобы меня тоже глючило, я предлагал дефрагментировать хип, зайти в какой-то кабинет в Токио, и путал хэш с кэшем? Не, я подожду стабильной версии в Дебильяне.

И тебя не смущает, что всякие гентушники и прочие федороводы будут более тонко чувствовать астральные волны, проникающую радиацию космической среды и прочий фэнь-шуй?

mv ★★★★★
()
Ответ на: комментарий от stpg

> IIRC - константные хеши разделяют работу на 2 фазы - записть, а потом чтение. Очередь на константных хешах будет сделать тяжелее - так как придется держать аж два буфера одновременно - один на запись, второй на чтение;)

1. Я вообще не про то.

2. Ты будешь удивлён, но в любом хэше всякая запись, прежде, чем будет прочитана, должна быть записана.

ЗЫ. Ты действительно не понял примера с кипечением чайника, или стебёшься?

Die-Hard ★★★★★
()
Ответ на: комментарий от stpg

> То, что я предложил - сделать очередь на диске.

Ты предложил её сделать крайнечереззадничным методом. Грубо говоря, ты предложил уже существующую очередь разбить случайным образом на фрагменты, а потом собрать их заново с использованием довольно "дорогих" универсальных технологий. И предложил для этого одну из самых "тяжёлых" реализаций этих технологий. Так понятно, надеюсь?

Die-Hard ★★★★★
()

купи второй сервер и размазывай запись на две(три, четыре, etc) железки или проапгрейди первый :).

true_admin ★★★★★
()
Ответ на: комментарий от mv

> И тебя не смущает, что всякие гентушники и прочие федороводы будут более тонко чувствовать астральные волны, проникающую радиацию космической среды и прочий фэнь-шуй?

Меня беспокоит, что они переловят всех маленьких зеленых чертиков :/

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> ...я предлагал дефрагментировать хип,...

Зря стебёшься!

Уверяю, если размеры чанков в линейном списке локально-возрастающие, ГНУтый маллок за час пережуёт гигабайт оперативки в мелкую труху. Много раз наступал...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> 2. Ты будешь удивлён, но в любом хэше всякая запись, прежде, чем будет прочитана, должна быть записана.

Что правда?;) Я про то, что константный хеш чуть-чуть меньше подходит для этой задачи, чем не константный.

> ЗЫ. Ты действительно не понял примера с кипечением чайника, или стебёшься?

Условий задачи недостаточно, что бы утверждать подходящий ли это метод или нет.

stpg
()
Ответ на: комментарий от Die-Hard

>> ...я предлагал дефрагментировать хип,...

> Зря стебёшься!

> Уверяю, если размеры чанков в линейном списке локально-возрастающие, ГНУтый маллок за час пережуёт гигабайт оперативки в мелкую труху.

Я не над этим стебусь. Просто из описания задачи об источнике проблем сказать нельзя практически ничего, но народ щедро предлагает решения %) Подозреваю, что по этому топику можно изучать, какие проблемы нанесли самые глубокие психологические травмы местным обитателям ;)

Я бы подождал ответа UVV - вдруг он фиксирует транзакцию после каждого записанного байта :)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> какие проблемы нанесли самые глубокие психологические травмы местным обитателям ;)

Доктор, какой у меня диагноз? :)

true_admin ★★★★★
()
Ответ на: комментарий от tailgunner

> Просто из описания задачи об источнике проблем сказать нельзя практически ничего

Конечно!

Я просто хотел обратить внимание UVV на то, что, возможно, дело не в слишком маленькой скорости работы БД, а во фрагментации хипа -- симптомы будут абсолютно те же.

Остальные мои пререкания -- оффтопик, каюсь (я ж теперь не модератор -- имею прво! :-) ).

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Ты предложил её сделать крайнечереззадничным методом. Грубо говоря, ты предложил уже существующую очередь разбить случайным образом на фрагменты,

Кто сказал фрагменты?

Документация по bdb: In Queue databases, records are allocated sequentially and directly mapped to an offset within the file storage for the database

> а потом собрать их заново с использованием довольно "дорогих" универсальных технологий. И предложил для этого одну из самых "тяжёлых" реализаций этих технологий. Так понятно, надеюсь?

Чем не энтерпрайзно?;) Я предложил готовую, всем известную, проверенную опытом технологию, на которой прототип решения сделать достаточно легко. Если решение окажется правильным, но всё таки не будет устраивать "вес" технологии - то можно поискать что то более кошерное=)

stpg
()
Ответ на: комментарий от stpg

> Условий задачи недостаточно, что бы утверждать подходящий ли это метод или нет.

Вполне достаточно. Этот метод, конечно, всегда подходит, но всегда _очень_ не оптимален ;).

Die-Hard ★★★★★
()
Ответ на: комментарий от stpg

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

Да, ты прав! Чтобы убить воробья, достаточно покрепче привязать его к дереву и в упор выстрелить из 120-мм пушки...

Одна проблема -- воробей-то не один! Пока ты его привязывать будешь да пушку заряжать, прочие воробьи разлетятся...

Die-Hard ★★★★★
()
Ответ на: комментарий от tailgunner

> И заметь - никакого libastral

Говорят, первые наработки libastral'а ещё входили в гццшный рантайм, и любая программа могла кастовать телепатов в тред. Но потом код, как всегда, чрезмерно раздули, завязали на glib, пришлось вынести в отдельную библиотеку.

mv ★★★★★
()
Ответ на: комментарий от Die-Hard

> Да, ты прав! Чтобы убить воробья, достаточно покрепче привязать его к дереву и в упор выстрелить из 120-мм пушки...

> Одна проблема -- воробей-то не один! Пока ты его привязывать будешь да пушку заряжать, прочие воробьи разлетятся...

Не совсем. По твоей аналогии - я предлагаю "подрезать скальпелем крылья воробьям, что бы он упал на землю, а дальше, проверенным способом, раздавить его катком". Но если такое действительно получится сделать - то можно же каток заменить на что-то типа "маленького катка";)

stpg
()
Ответ на: комментарий от stpg

> я предлагаю "подрезать скальпелем крылья воробьям, что бы он упал на землю, а дальше, проверенным способом, раздавить его катком".

Правильный ответ: зарядить такую пушку, чтобы всех воробьёв нах одним выстрелом накрыло.

mv ★★★★★
()
Ответ на: комментарий от Die-Hard

> Вполне достаточно. Этот метод, конечно, всегда подходит, но всегда _очень_ не оптимален ;).

Ну не оптимален, соглашусь. Но быстр в реализации. Ведь что бы сделать очередь на диске - не всегда надо писать напрямую на диск, написав специальный драйвер?:)

stpg
()
Ответ на: комментарий от mv

> Правильный ответ: зарядить такую пушку, чтобы всех воробьёв нах одним выстрелом накрыло.

Это негуманный метод. Дерево может пострадать!

stpg
()

В общем случае очередь должна быть блокирующей.

Пример - пайп в баше: напиши cat /dev/urandom |hexdump |less, увидишь, что никакого переполнения памяти нет, все процессы спят, ждут less'а.

Так и в общем случае - у очереди должен быть заранее определённый предельный объём, а первый поток должен блокироваться при попытке записи в очередь, если та заполнена, до момента, когда очередь достаточно опустеет. К слову, блокируется точно так же, как и (обычно) второй поток блокируется при попытке чтения пустой очереди, пока не появятся данные.

Все остальные "решения", возможно, замечательно подойдут к твоей конкретной задаче, но не являются "прямым путём".

PS. читал тред, осилил только начало обсуждения; возможно, я повторяю то, что кто-то уже написал.

alexsaa
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.