|
|
|
| Есть задачка загружать log файлы в базу MySQL и, естественно,
делать выборки на основе этих данных.
Код загрузки данных на PHP:
<?php
$handle = fopen("$userfile", "r");
while (!feof($handle))
{
$buffer = fgets($handle);
$buffer=ltrim($buffer);
// ну и так далее
}
fclose($handle);
?>
Есть две системы, на которых проводилось тестирование:
1. Windows 2000Pro, Apache 2.0.52, MySQL 4.1.14, PHP 5.0.2
2. ALTLinux 2.4 Master & Apache, MySQL, PHP - стандартные
из дистрибутива.
Опытным путем было установлено, что на Windows log-файлы
размером больше 700 строк загружаются нестабильно, т.е.
может зарузиться от 700 до 1000 строк.
Более того скорость работы в Windows в разы больше по
сравнению с Linux.
Есть способ уравнять шансы обеих систем или поставить крест
на Windows, как платформу для подобного рода задач?
Александр aka DarkLord | |
|
|
|
|
|
|
|
для: DarkLord
(10.03.2006 в 11:30)
| | А файлы локальные или удаленные?
Как-то очень слабо верится в то, что если более ничего не мешает, системе (любой!) не прочитать 1000 строк из файла.
Что там прячется в //ну и так далее ? | |
|
|
|
|
|
|
|
для: Trianon
(10.03.2006 в 12:02)
| | Файлы локальные - обмен по Ethernet.
Неважно, что прячется. Код ОДИНАКОВЫЙ выполняется на одной и той же машине, только на разных ОС. Мне тоже не верилось, пока сам не убедился. | |
|
|
|
|
|
|
|
для: DarkLord
(10.03.2006 в 14:54)
| | Если бы такую задачу решал я, то наверное бы сделал чтение файла порциями по 64-128кБ, из порции забирал бы строки, и заносил из в базу одним оператором INSERT. И код скорее всего устойчиво работал бы на любой ОС. С разной скоростью - да. Но не ломался бы - точно. | |
|
|
|
|
|
|
|
для: Trianon
(10.03.2006 в 15:00)
| | А почему такие глюки есть предположение?
Т.к. это довольно серьезные нарекания и переписывать код только
для того, чтобы все работало под виндами нет никакого резона.
Для нормальной задачи всегда лучше выбивать отдельную машину,
а если машина отдельная, то выбор ОС очевиден. | |
|
|
|
|
|
|
|
для: DarkLord
(10.03.2006 в 16:15)
| | >А почему такие глюки есть предположение?
Тут можно только гадать. В чем именно состоит глюк, помимо того, что скрипт не работает с длинными файлами, Вы не сообщили. В тех строках кода, которые Вы привели, всё чисто.
>Т.к. это довольно серьезные нарекания и переписывать код только
>для того, чтобы все работало под виндами нет никакого резона.
Безусловно, Вы сами будете решать, каким именно способом справляться с проблемой.
У меня и в мыслях не было навязывать Вам тот или иной путь. | |
|
|
|
|
|
|
|
для: Trianon
(10.03.2006 в 16:32)
| | >>А почему такие глюки есть предположение?
>Тут можно только гадать. В чем именно состоит глюк, помимо того, что скрипт не работает с >длинными файлами, Вы не сообщили. В тех строках кода, которые Вы привели, всё чисто.
В случае больших файлов загружает от 700 до 1000 строк, причем закономерность непонятна,
т.е. скрипт выполняется не до конца. | |
|
|
|
|
|
|
|
для: DarkLord
(10.03.2006 в 17:03)
| | Это надо понимать так, что Вы включили все средства диагностики (error_reporting), но они не дали результата. Скрипт отрабатывает безо всяких сообщений и вываливается потому, что внезапно и неожиданно наступает условие feof($handle). Вот на этот момент и надо акцентировать внимание. Отсюда повторный вопрос.
Файл, который Вы открываете, действительно локальный? Т.е. размещенный на машине со скриптом, apache, PHP-интерпретатором и проч.? Или он живет где-то в локальной сети?
Тогда он, простите, удаленный.
Спрашиваю, потому что совершенно не понимаю, какой смысл поднимать еще один сервер, чтобы он собирал свои собственные логи. Других локальных у него нет и быть не может. | |
|
|
|
|
|
|
|
для: Trianon
(10.03.2006 в 17:50)
| | >Отсюда повторный вопрос.
>Файл, который Вы открываете, действительно локальный? Т.е. размещенный на машине со >скриптом, apache, PHP-интерпретатором и проч.? Или он живет где-то в локальной сети?
>Тогда он, простите, удаленный.
>Спрашиваю, потому что совершенно не понимаю, какой смысл поднимать еще один сервер,
>чтобы он собирал свои собственные логи. Других локальных у него нет и быть не может.
Файл пробовал как локальный, так и удаленный - результат один.
Отдельный сервер (статистики) создается для обработки лог-файлов другого сервера,
который занимается своей основной работой. Как попадают лог-файлы - это уже
дело десятое. Они вполне могут загружаться локально.
>Это надо понимать так, что Вы включили все средства диагностики (error_reporting), но они не дали >результата. Скрипт отрабатывает безо всяких сообщений и вываливается потому, что внезапно и >неожиданно наступает условие feof($handle). Вот на этот момент и надо акцентировать внимание.
А вот по поводу средств диагностики я бы не отказался от дельных советов, т.к. их не использую.
Я накатал тестовые скрипты, которые наглядно демострируют данную ситуацию.
Текущие эксперименты провожу на Windows.
Создаю тестовый лог-файл, на основе которого будет проводиться тестирование:
<?php
// предварительное удаление существующих таблиц
$query="drop table if exists sessions";
if($result=mysql_query($query)) echo "<br>Таблица sessions удалена.<br>";
else echo "<br><font color=red><b>Ошибка удаления таблицы sessions.</b></font><br>";
// создаем таблицы
$query="create table sessions (
id int unsigned not null auto_increment,
dat datetime not null default '0000-00-00 00:00:00',
num int not null,
primary key (id)
)";
if($result=mysql_query($query)) echo "<br>Таблица sessions успешно создана.<br>";
else echo "<br><font color=red><b>Ошибка создания таблицы session.</b></font><br>";
$handle = fopen("test.txt", "w");
$somecontent="13/03/2006 11:19:27 ";
$commentcontent="Здесь будут какие-то комментарии \n";
for($i=1; $i<=1500; $i++)
{
$tempcontent = $somecontent;
$tempcontent .= "$i \n";
if (fwrite($handle, $tempcontent)) echo "Строка номер $i записана.<br>";
if (!fmod($i, 20))
if (fwrite($handle, $commentcontent)) echo "Комментарий записан.<br>";
}
fclose($handle);
?>
|
Для цикла 1500 получаем файл размером 40К, а для 150000 - 3,7М.
Путем экспериментов выяснено, что основную задержку при чтении лог-файла
вносит функция записи данных в MySQL.
Поэтому в этих тестах она закоментирована.
<?php
// ставим скрипт "на счетчик" (чтобы знать, как долго он выполнялся
$ttt=microtime();
$ttt=((double)strstr($ttt, ' ')+(double)substr($ttt,0,strpos($ttt,' ')));
$j=0;
$handle = fopen("test.txt", "r");
while (!feof($handle))
{
$buffer = fgets($handle);
$buffer=ltrim($buffer);
$mbuf=substr("$buffer",0,10);
if (ereg ("([0-9]{2})/([0-9]{2})/([0-9]{4})", $mbuf))
{
$j++;
list($day, $month, $year, $hour, $minute, $second, $num) = sscanf($buffer, "%d/%d/%d %d:%d:%d %d");
echo "Строка $j прочитана.<br>";
$isodate = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $hour, $minute, $second);
// $query="insert into sessions (id, dat, num) values (null, '$isodate', '$num')";
// if($result=mysql_query($query)) echo "Сеанс связи записан: $isodate $num <br>";
// else echo "<font color=red><b>Ошибка записи сеанса связи.</b></font><br>";
}
}
fclose($handle);
echo "<br><br><b>Всего загружено $j сеансов.</b><br>";
// считаем, как долго работал скрипт
$ddd=microtime();
$ddd=((double)strstr($ddd, ' ')+(double)substr($ddd,0,strpos($ddd,' ')));
echo ("<br>Время индексации: ".(number_format(($ddd-$ttt),3))." секунд<br>");
?>
|
Если раскомментировать функцию записи данных в базу MySQL, то ситуация повторяется -
скрипт до конца не доходит. | |
|
|
|
|
|
|
|
для: DarkLord
(13.03.2006 в 11:01)
| | Так может скрипт просто слишком долго выполняется? У PHP по умолчанию на выполнение всего скрипта таймаут в 30 секунд. | |
|
|
|
|
|
|
|
для: Trianon
(13.03.2006 в 11:18)
| | Очень похоже на правду.
Если так, то для меня вывод очевиден: т.к. винду не заставить работать быстрее,
то буду делать только на Linux.
ЗЫ Как насчет отладчика? Как им пользоваться? | |
|
|
|
|
|
|
|
для: DarkLord
(13.03.2006 в 12:28)
| | Мне стало грустно. Настолько, что я написал вот это:
<?php
// ставим скрипт "на счетчик" (чтобы знать, как долго он выполнялся
$ttt=microtime();
$ttt=((double)strstr($ttt, ' ')+(double)substr($ttt,0,strpos($ttt,' ')));
$j=0; $blk_factor = 16384;
$handle = fopen("test.txt", "r");
$block = ''; $sep = "\n";
while (!feof($handle))
{
$block .= fread($handle, $blk_factor);
// $buffer=str_replace(array("\r", "\n"), array("#", $sep), $buffer);
$lines = explode($sep, $block);
$cnt = count($lines);
$block = $cnt <= 1 || substr($block,-1,1) == $sep
? "" : $lines[--$cnt];
if($block != "")
unset($lines[$cnt]);
$query="insert into sessions (dat, num) values "; $rsep = '';
foreach($lines as $buffer)
{
$buffer=ltrim($buffer);
$mbuf=substr("$buffer",0,10);
if (ereg ("([0-9]{2})/([0-9]{2})/([0-9]{4})", $mbuf))
{
$j++;
list($day, $month, $year, $hour, $minute, $second, $num) = sscanf($buffer, "%d/%d/%d %d:%d:%d %d");
//echo "Строка $j прочитана.<br>";
$isodate = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $hour, $minute, $second);
$query .= "$rsep('$isodate', '$num')"; $rsep = ',';
}
}
if($result=mysql_query($query)) echo "Сеансы связи записаны по : $isodate $num <br>";
else echo "<font color=red><b>Ошибка записи сеанса связи.</b></font><br>";
}
fclose($handle);
// считаем, как долго работал скрипт
$ddd=microtime();
$ddd=((double)strstr($ddd, ' ')+(double)substr($ddd,0,strpos($ddd,' ')));
echo ("<br>Время индексации: ".(number_format(($ddd-$ttt),3))." секунд<br>");
?>
|
Поглядите... поиграйте параметром blk_factor.
И подумайте, о том, что стоит сократить бешеную работу оценки синтаксиса строк.
Думаю, кое-какой эффект Вы увидите.
PS. Для отладки я использую echo '<pre>'; print_r($var); А под средствами диагностики имел в виду error_reporting = E_ALL в php.ini. | |
|
|
|
|
|
|
|
для: Trianon
(13.03.2006 в 14:09)
| | Спасибо за великолепный пример.
Действительно все заработало на отлично.
Не судите меня сильно строго - я начал программировать на PHP недавно,
и уровень у меня невысокий.
Тем не менее все вышеизложенное моего последнего мнения не меняет. | |
|
|
|
|
|
|
|
для: DarkLord
(13.03.2006 в 16:28)
| | Сколько времени выполняется? При каком блок-факторе? На какого размера логе? Интересно же...
А PHP я тоже недавно изучаю. Так что у Вас тоже скоро все будет ОК :) | |
|
|
|
|
|
|
|
для: Trianon
(13.03.2006 в 16:53)
| | Докладываю. ;-)
Системник: процессор Celeron 1,7 Ghz, 384 Mb оперативки.
1-ая система: Windows 2000pro, Apache 2.0.52, MySQL 4.1.14, PHP 5.0.2
2-ая система: ALTLinux 2.4 Master, Russian Apache PL30.20, MySQL 4.0.20, PHP 4.3.9
Размера оперативной памяти в системе хватало.
Тестировал на лог-файлах след размерах:
1. 419 Kb, 15000 записей
2. 3,3 Mb, 113851 записей
3. 3,7 Mb, 129433 записей
Результаты тестирования (время работы скрипта в секундах):
1 2
1 1,9 1,25
2 15,3 10,00
2 16,8 11,00
Очевидны преимущества использования Linux.
DarkLord
ЗЫ Я и стремлюсь чтоб с PHP все было хорошо, но и желательно
получать от этой деятельности не только моральное удовлетворение. | |
|
|
|
|
|
|
|
для: DarkLord
(14.03.2006 в 10:14)
| | По-моему, время выполнения в разных ОС отличается не на порядок. И даже не в разы. Так что выбор ОС жестко на этом аспекте не завязан, и его можно выполнять по другим критериям. Например, по удобству администрирования Вами, по уровню имеющегося опыта работы, или пр.
Попробуйте поиграть блокинг-фактором. Увеличить в 2-10 раз, уменьшить в 2-10 раз. Возможно, что при увеличении блокинг-фактора, скорость еще вырастет. Главное, не перестараться. Найти значение, при котором рост становится уже незначительным, и на нем работать. Это позволит и память сэкономить и время особо не тратить. | |
|
|
|
|
|
|
|
для: Trianon
(14.03.2006 в 10:29)
| | Если я не ошибаюсь, то Apache и MySQL первоначально создавались для Unix систем и, естественно, больше оптимизированы для них.
Могу накатать еще кучу тестов, на выборках из базы и пр. на которых будет видно это преимущество, но мне лень. А по поводу данного примера, то, конечно, выберу оптимальный размер блока, но уже ближе к завершению написания программы.
По поводу удобства администрирования (не говоря уже о надежности) я все чаще свой выбор делаю в пользу Linux.. | |
|
|
|
|
|
|
|
для: DarkLord
(14.03.2006 в 11:28)
| | MySQL оптимизируется под каждую операционную систему отдельно... Более того в Windows (как в прочем и Linux) она себя чувствует лучше, чем даже в FreeBSD... | |
|
|
|
|
|
|
|
для: DarkLord
(10.03.2006 в 11:30)
| | > MySQL оптимизируется под каждую операционную систему отдельно...
> Более того в Windows (как в прочем и Linux) она себя чувствует лучше, чем даже в FreeBSD...
А где взять рекомендации (или статьи) по оптимизации работы MySQL под Windows ? | |
|
|
|
|
|
|
|
для: DarkLord
(02.05.2006 в 09:20)
| | А что хотите настроить и для каких целей?
PS Под новые вопросы лучше заводить новые темы в разделе MySQL | |
|
|
|
|
|
|
|
для: cheops
(02.05.2006 в 11:53)
| | Хорошо.
Сделал новую тему в разделе MySQL:
http://www.softtime.ru/forum/read.php?id_forum=3&id_theme=16911&page=1
Переношу обсуждение вопросов туда. | |
|
|
|
|