Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 11:16 |
Нужно работать с большими файлами или с большими объемами файлов. Более конкретно, осуществлять по ним разный хитрый поиск.
Файлов у меня 100 000, по несколько кило каждый. Если работать со всеми по очереди, получается медленно. По моим подсчетам:
Прочесть 100 000 файлов по 2k и найти в них строку - 15 секунд.
Прочесть 200Mb (200 файлов по 1Mb) и найти в них строку - 1 секунда.
А если объединить их в один большой файл, получается быстро, но PHP начинает вылетать, когда файл становится больше 10Mb (а я гружу его в массив).
По ряду причин хочется обойтись без MySQL и других БД, работать только средствами PHP.
И там же еще проблема встает. Несколько пользователей могут одновременно писать в один файл. Как сделать так, чтобы они друг другу не мешали, есть готовые рецепты?
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 11:57 |
А зачем грузить его в массив, нельзя разве просто последовательно по одной строке считывать?
Код: |
$fp = fopen("path_to_file", "r");
while($line = fgets($fp))
{
//do something with $line
}
fclose($fp);
|
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 12:11 |
Да, это мысль. Хоть и геморройнее, но вполне реально.
Только как мне удастся вставить строку в файл 200Mb? Переписывать и переименовывать?
|
|
|
|
С нами с 01.10.03
Сообщения: 751
Рейтинг: 318
|
Добавлено: 29/04/06 в 12:13 |
не надо файл одной строкой делать
наоборот, строчек должно быть много
потом читаешь по одной строчке до появления нужного тебе фрагмента
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 12:18 |
Да, это я понял. Пусть там будет, допустим, миллион строк по 200 байт. И вот мне понадобилось вставить строку в середину файла. Как это возможно сделать быстро?
|
|
|
|
+ + +
С нами с 26.04.06
Сообщения: 244
Рейтинг: 82
|
Добавлено: 29/04/06 в 12:24 |
Никак. Только перемещать вторую половину на 200 байт.
Можно еще создать файл индексов подгружать его в массив, производить необходимые действия по изменению порядка строк в большем файле и записывать индексы назад.
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 12:31 |
Sokira писал: | Можно еще создать файл индексов подгружать его в массив, производить необходимые действия по изменению порядка строк в нем и записывать назад в файл. |
То есть, вместо того, чтобы искать через файловую систему, склеить файлы в один большой, и сделать аналог собственной файловой системы в нем?
Надо будет поставить опыт, насколько это ускорит процесс.
А где, кстати, в PHP хранятся максимальные размеры переменной, строки, массива и т.д.?
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 12:41 |
В php.ini переменная memory_limit. По умолчанию она равна 8М, попробуй поменять значение, тоже вариант...
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 12:46 |
О! Супер! Сейчас поставлю в 200...
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 12:53 |
Петр Кроликов писал: | Да, это я понял. Пусть там будет, допустим, миллион строк по 200 байт. И вот мне понадобилось вставить строку в середину файла. Как это возможно сделать быстро? |
Используй временные файлы, переписывай в него все до того места, которое вставить, потом вставка, потом окончание файла, примерно так
Код: |
$line_to_insert = "Bla-bla-bla";
$line_after_insert = "Bu-bu-bu";
$fp = fopen("path_to_file", "r");
$tmp = tmpfile();
while($line = fgets($fp))
{
fwrite($tmp, $line);
if($line == $line_after_insert)
fwrite($tmp, $line_to_insert);
}
fclose($fp);
//some actions
$fp = fopen("file_to_write", "w");
fseek($tmp, 0);
while($new_line = fgets($tmp))
{
fwrite($fp, $new_line);
}
fclose($tmp);//delete temp file
fclose($fp);//file with insert string |
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 13:07 |
Какая-то херь после опытов таинственная
Лимит памяти 8М. Тем не менее, командой file() PHP уверенно грузит файл на 200Mb в массив и делает поиск по нему. Как помещается 200Mb в 8-ми выше моего понимания.
По времени выигрыша ни хера нет: ищет гад столько же примерно, сколько и по набору мелких файлов. от 7 до 18 секунд, в зависимости от сложности поставленной задачи.
Так что походу надо просто кэшировать мелкие файлы и ставить мощный сервер
|
|
|
|
С нами с 01.10.03
Сообщения: 751
Рейтинг: 318
|
Добавлено: 29/04/06 в 13:22 |
кстати
что-то мне кажется, что тесты на ХР могут сильно отличаться от боевой работы на NIX, или какая у тебя там ось на сервере стоит
ведь файловые системы устроены и работают по разному
простветите знающие
может имеет смысл поставить виртуальную машину под виндой и на ней тестить?
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 13:24 |
Петр Кроликов писал: | Какая-то херь после опытов таинственная
Лимит памяти 8М. Тем не менее, командой file() PHP уверенно грузит файл на 200Mb в массив и делает поиск по нему. Как помещается 200Mb в 8-ми выше моего понимания.
По времени выигрыша ни хера нет: ищет гад столько же примерно, сколько и по набору мелких файлов. от 7 до 18 секунд, в зависимости от сложности поставленной задачи.
Так что походу надо просто кэшировать мелкие файлы и ставить мощный сервер |
Не пробовал file_get_contents()
А с лимитом скорее всего тебе надо сервер перезапустить
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 13:26 |
proc3nt, запустил твой скрипт. Время выполнения не порадовало (около 16 секунд на 100Mb файле).
Jam, было бы здорово найти где-нибудь живые цифры. Типа, машина такая-то, NIX такой-то, скорость открытия такая-то, чтения такая-то...
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 13:26 |
Jam писал: | кстати
что-то мне кажется, что тесты на ХР могут сильно отличаться от боевой работы на NIX, или какая у тебя там ось на сервере стоит
ведь файловые системы устроены и работают по разному
простветите знающие
может имеет смысл поставить виртуальную машину под виндой и на ней тестить? |
Поставишь виртуальную машину, бкдет еще хуже, она тоже ведь ресурсы жрет
Поробуй на сервере побаловаться, и ставь в код, чтобы время засекалось, прямо интересно стало, как на Юнихах будет
|
|
|
|
С нами с 01.10.03
Сообщения: 751
Рейтинг: 318
|
Добавлено: 29/04/06 в 13:29 |
дык я понимаю что будет хуже, но как ни как ближе к реальности, а вообще то конечно лучше сразу на хосте пробовать
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 13:41 |
proc3nt писал: | Не пробовал file_get_contents() |
Попробовал, действительно повеселее.
Цитата: | $time1 = time();
echo "Вхождений: ";
echo substr_count(file_get_contents('TEMP/test.txt'),"111") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"222") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"333") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"444") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"555") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"666") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"777") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"888") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"999") . ", ";
echo substr_count(file_get_contents('TEMP/test.txt'),"000");
$time2 = time();
echo ". Время выполнения (в секундах): " . ($time2 - $time1); |
Первый поиск 13 секунд, последующие 12 секунд. То есть, один поиск для кешированного файла - 1.2 секунды. Меня это вполне устраивает.
Еще бы на 100 000 мелких с такой скоростью работать
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 13:49 |
Может вот так попробовать
Код: |
$time1 = time();
$file_info = file_get_contents('TEMP/text.txt');
echo "Вхождений: ";
echo substr_count($file_info,"111") . ", ";
echo substr_count($file_info,"222") . ", ";
echo substr_count($file_info,"333") . ", ";
echo substr_count($file_info,"444") . ", ";
echo substr_count($file_info,"555") . ", ";
echo substr_count($file_info,"666") . ", ";
echo substr_count($file_info,"777") . ", ";
echo substr_count($file_info,"888") . ", ";
echo substr_count($file_info,"999") . ", ";
echo substr_count($file_info,"000");
$time2 = time();
echo ". Время выполнения (в секундах): " . ($time2 - $time1);
|
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 13:52 |
4 секунды
|
|
|
|
С нами с 18.01.06
Сообщения: 322
Рейтинг: 487
|
Добавлено: 29/04/06 в 13:53 |
вот-вот, мы уже ближе к ответу
|
|
|
|
+ + +
С нами с 26.04.06
Сообщения: 244
Рейтинг: 82
|
Добавлено: 29/04/06 в 14:18 |
При затевании серьезных вещей не стоит искать выход в PHP. Достаточно создать структуры данных и методы ее обработки.
Например если у тебя строки в файле в 200 метров по 200 байт упорядочены по алфавиту, то поиск может занять не более 0,05 сек методом половинного деления. Если же файл нужно изменять, то можно применять его индексацию. Еще можно работать путем бинарного дерева - тогда вобще данные будут в наиболее гибком и быстром виде хранится, но правда усложнятся алгоритмы их обработки.
|
|
|
|
Ревнивый муж подобен турку
С нами с 01.03.06
Сообщения: 4302
Рейтинг: 905
|
Добавлено: 29/04/06 в 15:47 |
Sokira писал: | Достаточно создать структуры данных и методы ее обработки. |
Угу, согласен. Как раз думаю над структурой данных. Склоняюсь все же сделать 100 000 файлов, плюс индексные файлы по критичным ко времени запросам.
Цитата: | Еще можно работать путем бинарного дерева - тогда вобще данные будут в наиболее гибком и быстром виде хранится, но правда усложнятся алгоритмы их обработки. |
Нашел в Гугле, что такое бинарное дерево и другие алгоритмы. Читаю, тихо матерюсь сквозь зубы.
|
|
|
|
С нами с 05.07.05
Сообщения: 439
Рейтинг: 331
|
Добавлено: 29/04/06 в 17:39 |
Петр Кроликов писал: | Угу, согласен. Как раз думаю над структурой данных. Склоняюсь все же сделать 100 000 файлов, плюс индексные файлы по критичным ко времени запросам.
Нашел в Гугле, что такое бинарное дерево и другие алгоритмы. Читаю, тихо матерюсь сквозь зубы. |
насколько помню с лекций, алгоритм бинаритрии не отлчался большой скоростью.
|
|
альтруист
FTPCash - Новинка! Рекоммендую.
|
3
|
|
|
С нами с 09.01.05
Сообщения: 11
Рейтинг: 17
|
Добавлено: 30/04/06 в 00:13 |
Петр Кроликов писал: |
И там же еще проблема встает. Несколько пользователей могут одновременно писать в один файл. Как сделать так, чтобы они друг другу не мешали, есть готовые рецепты? |
http://php.net/manual/ru/function.flock.php
|
|
|
|
+ + +
С нами с 26.04.06
Сообщения: 244
Рейтинг: 82
|
Добавлено: 30/04/06 в 00:35 |
Gatos+ писал: | насколько помню с лекций, алгоритм бинаритрии не отлчался большой скоростью. |
Это смотря какими руками его писать. В идеале должно получаться log2N поисков, а на практике в лучшем случае log2N + 0.25
Но не стоит забывать, что есть еще B-tree, B+-tree, B*-tree...
|
|
|
|