Здраствуйте! Подскажите с чем может быть связана ошибка Out of memory когда скрипту требуется памяти >1,5ГБ? (нужно обработать массив данных, который и загружается весть в память) В PHP.ini memory_limit = 2500M Ошибка вылетает на PHP Version 5.2.4 с начала подумал что возможно глюк сборки - скачал последнюю PHP Version 5.2.9-2, в ней уже ошибка Out of memory не появляется, но скрипт не завершается, а все время выполняется, открыв диспетчер задач (все крутится на WinXP SP3 + Denwer, опетаривки 3,25ГБ, в boot.ini дописан ключ 3GB) видно что процес потредляет, потредляет память, как уровень потреьления памяти доходит до 1514 МБ - объем потребляемой памяти идет на спад до 0, потом процесс похоже перезапускается и снова так покругу пока не остановлю выполнение процесса.
Fatal error: Out of memory (allocated 1587544064) (tried to allocate 393216 bytes) разделение данных на части невозможно, использование БД тоже(скорость очень низкая).
Вот код Код (Text): $file = fopen("data.txt","r"); while (!feof ($file)) { $w = explode("=", fgets ($file, 512)); $gen[$w[0]]=$w[1]; } данные считываются из файла и заносятся в массив, данных всего 500МБ, но 30млн строк(так много памяти скорее всего пожирает организация структуры двумерного массива)
Мешает то, что нужно все данные загнать в память, а потом с ними работать, не выгружать/конвертировать а именно работать, по аналогии как загружают в память индекс для поиска по БД, так и тут этот файл должен структурированно лежать в массиве, который полностью в памяти.
bimcom Вам не PHP нужен, а C/C++, Java или ещё что-нить с типизированными типами данных. PHP для такого никак не предназначен, и уж точно не для лопачиния такого кол-ва данных в памяти.
Psih Скорее всего вы правы, но знаю я покачто только PHP, на изучение других языков времени свободного нет. В принципе PHP меня полностью устраивает и все на нем работает, только с большим объемом данных чет косяк, темболее на таком значение 1514 МБ, понимаю было место глюка 4 ГБ или 2ГБ (то что винда больше не выделяет, но вроде ключ прописал чтоб выделяла до 3х ) или было какоенибудь ограничение у PHP (например процесс больше 1,5ГБ не потребляет). В объщем непонятно почему ругается на нехватку памяти - ведь её полно, и в логи никаких ошибок не пишет. Может народ протестите у себя - сколько данных залить в память сможите, забив масси случайными цифрами? и отпишите у кого ошибка на 1,5ГБ не вылетела + сообщите персию ПХП.
bimcom У меня memory_limit вообще закоменнтирован, тоже на 1.5Гб вылетает. Полагаю, это связано с ОС. Неверю (c) ;-)
Представьте (в реальности данные похожи, но уровень энтропии выше) Есть список в файле ФАМИЛИЯ ИМЯ=количество человек есть источник данных который поставляет новые пары ФАМИЛИЯ ИМЯ теперь нужно в банке данных увеличить число человек имеющих такуюже ИМЯ ФАМИЛИЯ на +1, а если такой пары ФАМИЛИЯ ИМЯ нет то создать и присвоить элементу кол-во =1 Код (Text): $gen["ПЕТР СЕРГЕЕВИЧ"]=5256781; $gen["АРТЕМ ВИКТОРОВИЧ"]=58975; $gen["АРТЕМ ЕВДОКИМОВИЧ"]=975; ... Если не держать это все в памяти, то скорость поиска и дозаписи/увеличения на 1 происходит крайне медленно. Пробовал делить на 3 массива: 1массив - первые слова 2массив - вторые слова 3массив - хэш_измассива1 хэш_измассива2=число но расход на 3й массив по памяти увеличивается (т.к. это уже 3х мерный массив) и выигрыша почти нет. PS. БД работает медленнее на порядок, такчто она рассматривается только в самом последнем и крайнем случае. PSS. Если есть мысли как можно оптимизировать то что я делаю буду рад услышать советы.
OMG!!! Во-первых, самая медленная БД будет работать на порядок быстрее этого монстра. Во-вторых, для очень быстрой работы с данными есть (по крайней мере в MySQL) тип таблицы HEAP (MEMORY), memcached в конце концов! В-третих, во всех СУБД есть кэширование, в вашем случае даже InnoDB не будет тормозить.
Чувствую что те тормаза которые были у меня с MySQL БД связаны с дефолтными настройками MySQL-я. Подскажите какие параметры нужно выставить если под базу я готов выделить 2,5ГБ оперативы Код (Text): key_buffer = 16K max_allowed_packet = 1M table_cache = 4 sort_buffer_size = 64K read_buffer_size = 256K read_rnd_buffer_size = 256K net_buffer_length = 2K thread_stack = 64K А также подскажите какие параметры нужно выставить если я захочу присвоить тип базе HEAP, чтобы сравнить производительность. PS. При создание индекса на поле из 2х слов (ставлю как уникальные) индекс получается равный данным(по объему).
Давайте по-порядку... Что такое в данном случае - "тормоза"? Сколько запросов было в секунду? При каких операциях? Какой тип таблицы? И желательно код, который работал с БД.
Тормаза - медленная работа. Запросов - 800-1000 в секунду (из них 30% селекты 40% апдейты 30% инсерты) Операции - все, а особенно что побудило перенести все вычисления в память, так это быстрая дефрагментация БД (фрагментировались как файл таблицы так и файл индексов, скорость фрагментирования 100 фрагментов/минута и при кол-ве фрагментов >1000 кол-во запросов в секунду падало до 100, после проведения дефрагментации все снова летало) код Код (Text): SELECT * FROM data WHERE 2gram ='"$Words"' LIMIT 0 , 1 если ничего не нашол Код (Text): INSERT INTO `data` ( `id` , `2gram` , `dop`) VALUES ('', '"$Words"', '') а если нашол то Код (Text): UPDATE `data` SET `dop` = '".$Dop."' WHERE `id` =".$row2["id"]." LIMIT 1 ; Теперь похоже понял откуда фрагментированность росла - из-за маленького кэша. PS. сейчас же скорость работы с массивом пропорциональна 10 000-15 000 запросам в секунду к БД. (сравнение было на данных что помещаются в память, и в БД залит такойже объем)
Кажется, я вас понял. PHP предназначен для работы с небольшими объемами информации, лучше всего php работает со строками. Если вы все же хотите использовать php, то рекомендую использовать memcached.
Польза от memcached для данной задачи будет минимальна, его функция - кэширование наиболее часто повторяющихся запросов для оптимизации READ-a. bimcom, Смотри в сторону Berkley DB, идеально подходит для твоего случая (oracle BDB, memcacheDB, ...). http://www.oracle.com/technology/produc ... b-perf.pdf
300 селектов в секунду - это не часто повторяющиеся READ'ы? memcached без разницы что хранить и для каких целей, чтение и запись работают одинаково быстро. Кроме того, встроеные фунции инкремента и дикремента.
В случае с мемкешд надо смотреть не на количество ридов в секунду, а на количество повторов идентичных запросов. Хорошо если данных сейчас 2ГБ и можно загрузить все данные сразу в память, а если через месяц уже будет 100 ГБ ? Где тут польза , если все запросы произвольны ? Про пользу мемкешд для записи это была шутка ? :roll:
Если bimcom собирался хранить все данные в памяти, то значит не планируется, что будет 100Гб. И вообще не 2Гб, а 500Мб. Я имел ввиду, запись в память через memcached.
Пока замутил следующим образом: увеличил key_buffer до 2,5ГБ и запросы инсерта сделал отложенными - в результате скорость работы в начале очень низкая, но через 10 минут все попадает в кэш и скорость взлетает до 15 000 запросов/сек (теперь узкое место поставщик данных ) Всем спасиба. (разбираться более подробно буду в этой проблеме когда данных будет на порядок больше)
Хочу всем дать совет. Когда программируете - будьте предельно осторожны. Я вот себе программировал на пхп, запросы выполнял, не успел оглянутся, как у меня уже Кубунту вместо Дебиана...