The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Контроль объема используемой памяти на Си, !*! Virius, 23-Дек-08, 12:04  [смотреть все]
Всегда были проблемы при работе с памятью, и сейчас возник следующий вопрос. У меня в программе на Си в Linux'е используется динамический список. Соответственно есть два потока: один добавляет в список записи, другой их обрабатывает и удаляет. Для выделения/очистки памяти используется *alloc/free. Добавление происходит быстрей удаления, что естественно ведет к постоянному росту списка, что в конечном счете может привести к переполнению памяти. Соответственно вопрос, как этого избежать? Можно ли, например, задать программе (внутри самой программы) какое-то ограничение на объем доступной памяти, и при этом, соответственно, определить момент, когда этот предел будет достигнут (в этом случае можно было бы делать паузу и ждать, пока снова не появится достаточно доступной памяти)? Просто подсчитывать количество выделенной памяти ведь не подойдет, так как выделяемые и освобождаемые участки памяти всегда разной длины, что ведет к дефрагментации и в конечном счете доступно будет гораздо меньше памяти, чем действительно свободно.

Кроме того, я пытался использовать процессы вместо потоков и разделяемую память, но в этом случае ограничение на объем доступной разделяемой памяти оказался слишком маленький (не то 32Мб, не то 64). Может кто-нибудь знает, как увеличить это ограничение хотя бы до 2Гб?

И забыл сказать. Программа написана под Red Hat Enterprise Linux 3.0 (ядро linux 2.4.21)

  • Контроль объема используемой памяти на Си, !*! Andrey Mitrofanov, 13:18 , 23-Дек-08 (1)
    >Добавление происходит быстрей удаления, что естественно ведет к постоянному росту
    > к переполнению памяти. Соответственно вопрос, как этого избежать?

    Неужели удалять быстрее, чем добавляешь??

    Может быть, подумать, кой чорт понёс^W^W^Wзачем тебе понадобились потоки/форки? Сделать _выводы_.

    Например, читать-писать _последовательно_ в __одном__ потоке. Или исхитриться и читать двумя или более потоками, коли уж один "не успевает" (это не избавляет от необходимости синхронизации/блокировки ресурсов или какого ни IPC; и разнесения читателей по разным cpu). Оптимизировать производительность читателя, чтоб успевал. Купить сервер, чтоб успевал. Купить много серверов, чтоб успевали. Ещё ускорять читателя - отложить часть работы, например, "синхронно" писать на диск, потом медленно/асинхронно оборабатывать. Диск он большой -- авось поместится.

    100рублейвкассублин!

    2Maxim Chirkov: Гы, куда страждущим переводить _деньги_ за консультацию? Заведи кошелёк opennet что ли?.. %-)) И доп.поле "[_  ] руб. в кассу!", и ключь-идентификатор для вписывания в квиток %) перевода, и "лампочку" [ОПЛАЧЕНО] на ответах. :D Желаю анонимно зарабатывать денег уважаемому сайту и немеряной, но оцененной Славы. Как бы ещё анонимных неплательщиком пиночить? %)

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

    Феерично.......

    >Может кто-нибудь знает, как увеличить это ограничение хотя бы до 2Гб?

    Вам, может быть, нужен програмист?

    >И забыл сказать. Программа написана под Red Hat Enterprise Linux 3.0 (ядро linux 2.4.21)

    Не-е-е, в интырпрайз программировании тут никто ничего не понимает... Это Вам на бизнес-кусы надо.

    • Контроль объема используемой памяти на Си, !*! Virius, 14:05 , 23-Дек-08 (2)
      Видимо моя ошибка, что не описал задачу подробней. Хотя и причин для смеха в своем текте я не нахожу.

      >Неужели удалять быстрее, чем добавляешь??
      >
      >Может быть, подумать, кой чорт понёс^W^W^Wзачем тебе понадобились потоки/форки? Сделать _выводы_.
      >

      Удаляю я как раз медленней, о чем и написал. Потому что первый поток только добавляет, а второй еще и обработкой занимается с записью обработанных данных в БД. Из-за работы с БД основные тормаза и идут. Поэтому и используется конвеер, чтобы успевать принимать данные. И в данный момент используются процессы (форки) с промежуточным буфером в разделяемой памяти. И тут-то встала проблема, что в разделяемой памяти буфер может быть не больше 32/64Мб. Как увеличить этот предел - мне не известно. Хочу перевести это дело на потоки, так как с потоками все данные находятся в одном адресном пространстве, но встает проблема с тем, как контралировать заполнение памяти так, чтобы не прейти к переполнению.

      >Например, читать-писать _последовательно_ в __одном__ потоке. Или исхитриться и читать двумя или
      >более потоками, коли уж один "не успевает" (это не избавляет от
      >необходимости синхронизации/блокировки ресурсов или какого ни IPC; и разнесения читателей по
      >разным cpu). Оптимизировать производительность читателя, чтоб успевал. Купить сервер, чтоб успевал.
      >Купить много серверов, чтоб успевали. Ещё ускорять читателя - отложить часть
      >работы, например, "синхронно" писать на диск, потом медленно/асинхронно оборабатывать. Диск он
      >большой -- авось поместится.
      >

      Двумя и более потоками читать не получится. Слишком муторно и труднореализуемо, если вообще реализуемо. Мощность сервера и без того достаточная. Вся загвоздка в том, что данные приходят быстрей, чем программа, успевает их записать в БД. Тут все утыкается в производительность дискового массива, который используется для хранения БД, но его заменить щас не возможно. Да и замена его на более быстрый думаю не сильно бы помогла. Поэтому все опять же возвращается к означенным мной ранее вопросом, на которые я надеюсь кто-нибудь таки сможет мне ответить.

      • Контроль объема используемой памяти на Си, !*! pavel_simple, 07:32 , 24-Дек-08 (4)
        1. менять дизайн проги по любому -- т.к. передача данных от процесса к процессу не есть верный способ.
        2. у современных БД есть асинхронные вызовы
        3. если БД не успевает это записывать из-за диска это одно, если из-за того что не оптимизированы запросы/таблицы это другое
        4. если БД оптимизировать нельзя, и запись не успевает нужно менять железо как не подходящее для задачи.


        всё это напоминает решение задачи "считаем трафик", только через Ж

        что хоть прога делает? -- частенько встречаются случаи с неверной постановкой задачи и соответствующей реализацией


  • Контроль объема используемой памяти на Си, !*! vic, 22:54 , 23-Дек-08 (3)
    >Всегда были проблемы при работе с памятью, и сейчас возник следующий вопрос.

    Изучайте матчасть и закрывайте пробелы.

    >У меня в программе на Си в Linux'е используется динамический список.

    переходите на с++ что ли, уже 2009 год на дворе и  эта ваша фраза как-то пугает, видимо наследуемый код, если нет, то страшно..

    >Соответственно есть два потока: один добавляет в список записи, другой их
    >обрабатывает и удаляет. Для выделения/очистки памяти используется *alloc/free.

    есть тулза от гугла (google perf tools или как-то так) которая подменяет стандартный malloc на свою реализацию заточеную под очень частое выделение/удаление памяти. Это типо для борьбы с дефрагментацией :)

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

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

    >Можно ли, например, задать программе (внутри самой программы) какое-то ограничение на
    >объем доступной памяти, и при этом, соответственно, определить момент, когда этот
    >предел будет достигнут (в этом случае можно было бы делать паузу
    >и ждать, пока снова не появится достаточно доступной памяти)?

    легко, можно даже снаружи перед запуском задать объем памяти для процесса:

    man ulimit ключ -v

    дальше если malloc вернет NULL, значит не может выделить, пора возвращать выделенное =)

    внутри программы системными вызовами getrlimit, getrusage, setrlimit.


    >Кроме того, я пытался использовать процессы вместо потоков и разделяемую память, но
    >в этом случае ограничение на объем доступной разделяемой памяти оказался слишком
    >маленький (не то 32Мб, не то 64). Может кто-нибудь знает, как
    >увеличить это ограничение хотя бы до 2Гб?

    видимо ulimit -l :)

    >
    >И забыл сказать. Программа написана под Red Hat Enterprise Linux 3.0 (ядро
    >linux 2.4.21)

    достаточно ядра, редкая софтина юзает особые уличный фичи всяких энтерпрайзов и т.п. :)

  • Контроль объема используемой памяти на Си, !*! f00l, 08:03 , 24-Дек-08 (5)
    >[оверквотинг удален]
    >участки памяти всегда разной длины, что ведет к дефрагментации и в
    >конечном счете доступно будет гораздо меньше памяти, чем действительно свободно.
    >
    >Кроме того, я пытался использовать процессы вместо потоков и разделяемую память, но
    >в этом случае ограничение на объем доступной разделяемой памяти оказался слишком
    >маленький (не то 32Мб, не то 64). Может кто-нибудь знает, как
    >увеличить это ограничение хотя бы до 2Гб?
    >
    >И забыл сказать. Программа написана под Red Hat Enterprise Linux 3.0 (ядро
    >linux 2.4.21)

    Основная ошибка постоянное выделение и высвобождение памяти (сам с таким сталкивался )
    Необходимо выделить память для фиксированного количества данных, и по мере необходимости увеличивать, тогда все будет работать корректно.  

  • Контроль объема используемой памяти на Си, !*! BigHo, 14:35 , 24-Дек-08 (6)
    >удаления, что естественно ведет к постоянному росту списка, что в конечном
    >счете может привести к переполнению памяти. Соответственно вопрос, как этого избежать?
    >Можно ли, например, задать программе (внутри самой программы) какое-то ограничение на
    >объем доступной памяти, и при этом, соответственно, определить момент, когда этот
    >предел будет достигнут (в этом случае можно было бы делать паузу
    >и ждать, пока снова не появится достаточно доступной памяти)? Просто подсчитывать
    >количество выделенной памяти ведь не подойдет, так как выделяемые и освобождаемые
    >участки памяти всегда разной длины, что ведет к дефрагментации и в
    >конечном счете доступно будет гораздо меньше памяти, чем действительно свободно.

    Программа играет роль буфера, сглаживающего пиковые нагрузки? Если так, видимо на стадии обработки допущен просчет. Как следует из последующих постов - это может быть неоптимальная конфигурация БД. Если не применять никаких оптимизаций, то скорость работы по INSERT запросам на однодисковой (не RAID) платформе где-то 200-300 запросов в секунду, и с ростом этой таблицы будет только уменьшаться. Я говорю про MySQL, но, думаю, что и для других БД это будет характерно - для БД важна пропускная способность диска, и скорость обработки мелких запросов.

    >Кроме того, я пытался использовать процессы вместо потоков и разделяемую память, но
    >в этом случае ограничение на объем доступной разделяемой памяти оказался слишком
    >маленький (не то 32Мб, не то 64). Может кто-нибудь знает, как
    >увеличить это ограничение хотя бы до 2Гб?

    Возникает впечатление, что вы пытаетесь бороться с последствиями проблемы, а не самой проблемой,.

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

    С точки зрения постановки задачи более ничего не приходит в голову.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру