За последние 24 часа нас посетили 17490 программистов и 1672 робота. Сейчас ищут 1944 программиста ...

Забота о скорости выполнения

Тема в разделе "Прочие вопросы по PHP", создана пользователем Davil, 25 сен 2006.

  1. Davil

    Davil Guest

    Есть скрипт. Работает, делает все, как надо. Но вот выполняется он слишком долго (около 15 секунд) жрет 100% проца и 5мб оперативы!(я уже подумал, не разместить ли мне этот топ в HUMOR). Вроде ничего особенного там нет и файлы по 2Кб, в чем может быть дело? Может кто знает?

    PHP:
    1.  
    2. <?php
    3. ini_set("session.use_trans_sid", true);
    4. $nickq = $_REQUEST['nick'];
    5. $passq = $_REQUEST['pass'];
    6. $nickq = trim($nickq);
    7. $passq = trim($passq);
    8. $passq = md5($passq);
    9. $nickq = strtolower($nickq);
    10. $pnu = "udb/online.u";
    11. $erru = false;
    12. $file = fopen("udb/users.dbs", "a+t");
    13. flock($file, LOCK_EX);
    14. $us = explode("\n", fread($file, (filesize("udb/users.dbs")+1)));
    15. for($i=0;$i<=count($us); $i++){
    16. $m = $us[$i];
    17. $m = trim($m);
    18. $r = strpos($m, "=");
    19. $nick = substr($m, 0, $r);
    20. $pass = substr($m, ($r+1));
    21. $nick = strtolower($nick);
    22. if($nick==$nickq && $pass==$passq){
    23. $filen = @fopen($pnu, "r+t");
    24. if(!$filen){
    25. $filen = fopen($pnu, "a+t");
    26. flock($filen, LOCK_EX);
    27. if(filesize($pnu)==0){
    28. $put = "**********\n";
    29. fputs($filen, $put);
    30. fclose($filen);
    31. $filen = fopen($pnu, "r+t");
    32. }
    33. }
    34. flock($filen, LOCK_EX);
    35. $uso = explode("\n", fread($filen, (filesize($pnu)+1)));
    36. for($i=0;$i<count($uso);$i++){
    37. $m = $uso[$i];
    38. $m = trim($m);
    39. if($m !== $nick && $i == (count($uso)-1)){
    40. fclose($filen);
    41. fclose($file);
    42. $_SESSION['auth']="OK";
    43. $_SESSION['nick']=$nick;
    44. setcookie("nick", $nick);
    45. $_SESSION['first']=true;
    46. Header("Location: http://{$_SERVER['SERVER_NAME']}{$hostpoddir}/chat.php");
    47. }
    48. if($m == $nick){
    49. $erru = true;
    50. break;
    51. }
    52. }
    53. }
    54. }
    55. fclose($filen);
    56. fclose($file);
    57. ?>
    58.  
    P.S. Если есть советы по коду, приму, т.к. он очень сырой и будет еще сотни раз апдетиться.
     
  2. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    файл users.dbs большой? отсюда и тормоза.
    или юзай SQLite или MySQL
     
  3. Davil

    Davil Guest

    Весит 2Кб.
    Принцип в том, чтобы все сделать без БД чисто на файловой структуре.
    Причем, перед тем, как я добавил $filen все работало отлично, может это как-то связано с перекресной блокировкой?(кстати, это мысль, надо прошерстить!)
     
  4. TiGR

    TiGR Активный пользователь

    С нами с:
    3 сен 2006
    Сообщения:
    39
    Симпатии:
    0
    Адрес:
    Ижевск
    А если попробовать сделать профайлинг или просто пройтись дебаггером?
     
  5. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    Davil, а вы специально файл "udb/online.u" открываете столько раз сколько строк в файле "udb/users.dbs" ? и при этом для каждой строки из "users.dbs" вы в цикле просматриваете все записи одного и того же файла "online.u"... (оправдание что это делается потому что online.u может измениться во время исполнения скрипта, сами понимаете - фигня !)

    Переделайте так:
    1) один раз грузится online.u, распихивается в ассоциированный массив, $online[$nick] = ...
    2) сравнение производится по индексам типа (isset($online[$user]))
    3) извращенные конструкции типа
    Код (Text):
    1. $file = fopen("udb/users.dbs", "a+t");
    2. flock($file, LOCK_EX);
    3. $us = explode("\n", fread($file, (filesize("udb/users.dbs")+1)));
    легко заменяются на $us = @file("udb/users.dbs");
     
  6. Davil

    Davil Guest

    Я думал, что код в операторе if() выполняется только при подтверждении условия...

    Выполняется интерпретатором в сотни раз быстрее, чем конструкция
    А блокировка мне необходима потому, что файл users.dbs может поменяться привыполнении этого кода.
    Предпочитаю пользоваться собаками только в виде исключения. В этом случае (как мне кажется) лучше обойтись без нее, иначе во время runtime может произойти нечто УЖАСНОЕ :)

    P.S. Спасибо за критику.
     
  7. Anonymous

    Anonymous Guest

    Davil, эта пять! =)
     
  8. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    во первых не те конструкции сравниваете - нужно было сравнивать с file(), а то с чем вы сравнили (оно вообще не относится к файловому вводу/выводу) уверяю вас работает намного быстрее.
    во вторых file() сработает быстрее чем fopen + explode("\n",fread()) хоть и делает тоже самое... посмотрите исходники самого php


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


    ужасное происходит обычно когда одну переменную используют во вложенных циклах, типа как у вас:
    Код (Text):
    1.  
    2. for($i=0;$i<=count($us); $i++){
    3.         for($i=0;$i<count($uso);$i++){
    а от собаки хуже не станет - она просто удавит warning если файл будет отсутсвовать, что вполне нормально при файловой организации данных, - просто не обращайте на нее внимание.
     
  9. Davil

    Davil Guest

    Ответ:
    Цитата из книги Дмитрия Котерова PHP5:

    $f = fopen($fname="file.txt", "rt");
    $lines = explode("\n", fread($f, filesize($fname)));

    Эти две строчки не только поместят в массив $lines все строки файла, но еще и:
    -- Удалят лишние символы перевода строки (\n);
    -- Удалят символы \r (на счет режима открытия файла "rt");
    -- Сделают это даже быстрее, чем сработала бы функция file().

    Последний пункт наводит на размышление, но простая проверка показывает: да, пара fread()+explode() работает быстрее, чем один вызов file(). Парадокс.



    Все - таки эта блокировка необходима из - за возможности синхронного использования этого скрипта с другим. При этом получится бяка :)

    Согласен, мой косяк. Спасибо за замечание.

    Я так и поступил. Причем сразу после этого сделал проверку данной функции на false.
     
  10. Anonymous

    Anonymous Guest

    Извини, но ты делал эту проверку?
     
  11. Davil

    Davil Guest

    Попробуй сам.
    Я видел результат.
     
  12. Davil

    Davil Guest

    Все, я нашел проблему. В файле, который вставлялся через require_once был лишний пробел. Странно, почему ошибка модификации хедеров не выводилась?
    Я уже написал почти все заново, а тут такая лабуда...
    Впринципе я выяснил несколько вещей, которые надо поменять вопреки совету главной страницы php.ru :)
     
  13. Davil

    Davil Guest

    ОПА! А куда совет дня убрали? :(
     
  14. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    туда ...