:-)
  • Мне нужно было получать строку из файла по порядковому номеру. То есть первую, десятую, 390815-ую, и т.д. Сначала мне хватало цикла fgets, который прокручивал до нужной строки. На строке 500000 такой способ у меня занимал уже почти минуту, что явно плохо. Stream_get_line был совем не быстрее, а даже медленнее процентов на 30.

    Первый из костылей, пришедших мне в голову был fseek до значения в 500000 строк (посчитал байты), а оттуда уже крутил fgets. Но так как у меня идет обработка до 100 тысяч строк в сутки, то через пару дней опять пришлось высчитывать смещение для fseek. Опять же, требовался другой выход. И я его таки нашел.

    function getFileLine($file, $line) {
        return trim(exec("head -n $line $file | tail -n 1"));
    }

    Head берет N первых строк файла, tail N последних. Все гениальное просто. 1 миллионная строка берется из файла за 1.027 сек, 40 миллионная - 30 секунд, что очевидно быстрее прокручивания fgets. (Конечно, если не прыгать fseek до 40 миллионной записи и считывать 40000001-ую)

    Конечно, решение ограничено *nix системами, но т.к. моя система и без того использует pcntl_fork, она уже была привязана к никсам, так что хуже мне не стало.

    А еще я писал про:

    1. Ошибка PDO Invalid Argument и Unix socket
    2. Многопоточность на PHP
    3. PHP: эксклюзивный счетчик в Shared Memory

    Tags: ,

  • 10 комментариев

    WP_Modern_Notepad
    • Snowcore пишет:

      Всемогущий Си!

    • Riot пишет:

      Да и вообще, использовать возможности платформы на которой все работает бывает полезно;)

    • epsyl пишет:

      А нечего такие объемы в файлах хранить

    • Alex Snet пишет:

      А как насчет производительности?

    • CharnaD пишет:

      Нагрузка процессора упала с 99% до 0-30%
      По времени 0,5-1 сек на чтение для меня в данном случае приемлемо.

    • Максим пишет:

      Решение конечно есть, но! есть крейзи-хостеры которые под виндой запускают пых и если ты просто арендуешь хостинг, тебе врятли дадут доступ к командной строке…

    • CharnaD пишет:

      Ну если вам надо обрабатывать файлы в сотни тысяч строк, полагаю, что рублей 250 в месяц на ВДС собрать можно.

      Ну а на хостерах да, такие трюки, скорее всего, не пройдут. Делайте fseek, крутите оттуда циклом fgets, каждые N итераций расчитывайте и запоминайте новую позицию для fseek.

    • Ad1ce пишет:

      Сомнительное решение
      Попробуйте выполнить
      sed ’40000000q;d’ filename
      И напишите сюда время выборки.

    • CharnaD пишет:

      white:/home/1# time sed ’40000000q;d’ file.lst
      PUMPING4LIFE

      real 5m38.109s
      user 2m1.152s
      sys 0m2.560s
      white:/home/1# time head -n 40000000 file.lst | tail -n 1
      PUMPING4LIFE

      real 0m46.676s
      user 0m7.320s
      sys 0m5.480s

      Нет, ваш способ не прокатывает.

    • Ad1ce пишет:

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

    Trackbacks

    Оставить комментарий

    Внимание: Комментарии проходят премодерацию. Не надо посылать их несколько раз.