В Си хорошо организовывать дебажные логи дефайнами.
#define LOG(msg) printf(msg);
LOG(«Hello»);

или
#ifdef DEBUG
printf(«Hello»);
#endif

В случае замены в дефайне принтфа на знаки комментария или если убрать константу DEBUG, то дебажный код полностью исключается из программы, никак не влияя на её производительность.

Можно ли что-нибудь подобное организовать в php?

const DEBUG = false;
if (DEBUG) …
Всё равно проверяет значение константы DEBUG, у меня компилятор php не оптимизирует такие участки. Можно ли это как-нибудь настроить?

Tagged with →  

61 Responses to В Си хорошо организовывать дебажные логи дефайнами.

  1. DnaSm:

    Надеюсь тебе поможет эта ссылка http://www.php.net/manual/en/ref.errorfu

  2. AmtEkb:

    iam_weasel: спасибо 🙂
    Я половиной этих функций уже пользуюсь, но хотел бы реализовать просто информационные сообщения для логов.

    Стандартный путь — указывание уровня логирования, например:
    log(0, «started»);
    log(4, «config after start is: «. serialize($config));

    function log($log_level, $msg) {
    if ($log_level < 2) return;
    debug_backtrace… blah-blah-blah… $log_msg = … $msg …
    file_put_contents($log_file, $log_msg);
    }

    Но если понаставить слишком много сообщений в лог, а потом зарубить уровень, то, получается, будет очень много вызовов функции log() впустую.
    Вот я и подумал — как бы их убрать вообще, чтобы даже пустых вызовов не было?

  3. DnaSm:

    а чего не использовать нотисы и не писать все в стандартный апачевский лог, а потом по флагу их фильтровать и выводить средствами линукс?

  4. Xuagreen:

    У тебя есть компилятор PHP? Ты молодец!

  5. DnaSm:

    Тебе вот это не подойдет? http://logging.apache.org/log4php/

  6. AmtEkb:

    iam_weasel: если писать всё, лог будет ужасно большим 🙂 Если писать не всё, останутся пустые вызовы 🙂

  7. AmtEkb:

    ну, я всегда думал, что php сначала компилирует скрипт в байт-код, а потом этот код выполняет. И надеялся, что в процессе компиляции идёт оптимизация.

  8. AmtEkb:

    iam_weasel: не, я пишу под phpdaemon, который запускается отдельными демонами. В нём запись в системный лог можно реализовать, но только самому вроде. Не знаю, не интересовался. В любом случае задача стоит лог вести в указанном отдельном файле. Системные функции лога же не могут писать в произвольный файл?

  9. Xuagreen:

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

  10. DnaSm:

    нет, насколько я помню. Но я тебе дал ссылку на уже готовую реализацию библиотеки логгирования, которая пишет куда хочешь.

  11. 5auam:

    могут, rtfm.

  12. AmtEkb:

    печально

  13. Kr0Blank:

    напиши препроцессор для пхп.

    (удиви мир)

  14. AmtEkb:

    iam_weasel: но ведь она будет заниматься тем же самым — всё равно будет вызываться, сравнивать уровень лога, возвращаться впустую. Так и так время будет тратиться. Я уж лучше тогда просто из продакшен версии все дебильные записи поудаляю, оставлю только нормальные, и всё 🙂

  15. AmtEkb:

    да тут уже без препроцессора особо активные личности пытаются меня отпинать, чтобы всё под хип-хопом компилилось 🙂

  16. Kr0Blank:

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

  17. LimZlo:

    На сколько процентов/миллисекунд медленнее работает твоя программа с вызовом функции log_…, чем с выкинутым кодом?

  18. AmtEkb:

    не мерял 🙂

  19. XibZZ:

    только если ты запускаешь php без опкод-кэшера (а в этом случае — ССЗБ).

  20. OkkGood:

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

    Ну и конечно, тот кто начал работать с демонами в пыхе, идут путями поиска нестандартных решений, таких как перезагрузка кода в runkit или использование libevent.

    Своими препроцессорами, там редко когда дело оборачивается.

  21. OkkGood:

    Зато я мерял. Если твоя программа в данный момент в отладочный лог ничего не пишет (читай «работает на продакшене»), то она практически никак не отличается от программы без функции логгирования.

    Естественно, при включении логирования производительность программы немного просядает. Что говорит о том, что отладочные сообщения лучше отключать на боевых машинах.

  22. AmtEkb:

    а как запустить его с опкод-кэшером?
    CLI режим его не предполагает, получается?

  23. AmtEkb:

    то есть хочешь сказать, что на кучу неполезных конструкций типа «if ($log_level > $max_log_level) return;» можно забить, так как они всё равно не внесут существенного вклада в производительность?

  24. OkkGood:

    Именно так.

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

    Вот тут небольшой пример http://pastebin.ru/RfOWPokn

    Если запустить его с уровнем «Логгировать только ошибки», время на итерацию миллиона ключей было 32 секунды,

    Если уровень «Не логгировать ошибки», время будет 12 секунд

    Если вообще закомментировать систему логгирования, то миллион ключей обработаются вхолостую ~ за 0.22

    Т.е. реальная потеря на систему логгирования, на обработку миллиона ключей будет ~ 11 секунд что на фоне общей производительности будет ничтожной цифрой 🙂

  25. AmtEkb:

    ну да, такой эксперимент я тоже делал.
    Хм. Ну ладно, посмотрим.

  26. Kr0Blank:

    разработка демонов, часто окупает затраты на неё.

    толстовато, не находишь?

  27. XibZZ:

    Почему не предполагает? Берешь да запускаешь. Ну в apc что-то там в конфиге поменять надо еще.

  28. OkkGood:

    Неа, не нахожу.

    Конечно же я сужу субъективно, так как сам привык к демонам на пыхе 🙂

    Понятно что в разработку демонов надо въезжать сперва, но потом демоны по скорости не сильно уступают программам написанным на питоне или си, и именно в этом случае разработка демонов на пыхе окупает затраты на неё 🙂

  29. AmtEkb:

    а ты на чём пишешь? с нуля или тоже используешь что-то типа phpdaemon?

  30. Nelef:

    Я хз как у вас там че в ПХП и зачем развели такой тред, но в чем проблема сделать так (это типа псевдокод):

    if DEBUG

    function log (params) = {log output here}

    else

    function log (params) = {empty fun}

    endif

    И вызывать log(params) везде не парясь?

  31. AmtEkb:

    ух ты, необычное решение, спасибо 🙂
    Но это решение не прокатит потому, что в продакшен версии всё равно будут какие-то логи.
    То есть в идеальном варианте функция в одних местах будет, а в других — нет, в зависимости от того, какой log_level ей в данном месте передаётся.

  32. Nelef:

    Ну переименуй ее в log_debug и пихай ее только в нужных местах, в остальных используй стандартные средства логирования. Я определенно не понимаю зачем все усложнять, на фоне очевидных решений.

  33. OkkGood:

    с нуля.

    Если честно, так и не посмотрел я на этот phpdaemon

  34. AmtEkb:

    да просто пришла мысль сделать совсем чисто и красиво 🙂 не получается. Ну и ладно.

  35. AmtEkb:

    ты крутой 🙂

  36. 5auam:

    тут всё сильно зависит от задач. у меня на продакшне пишется много логов финансовых операций (помимо базы, конечно) — они не сильно отличаются от отладочных.

  37. OkkGood:

    Жизнь заставила 🙂

  38. XibZZ:

    он местами странно написан как-то, прямо скажу

  39. OkkGood:

    И это, наверняка хорошо 🙂

    Главное что он дал в массы фреймворк для написания демонов

  40. AmtEkb:

    более чем. Там даже встречаются иногда такие моменты как
    function DeleteItem($item_id) {
    $items[$item_id] = new Item();
    }

    Только в последней сборке заменено на unset() 🙂

  41. Kr0Blank:

    ну это очевидное решение, но я так понял — автор хочет сэкономить даже на вызовах функций 🙂

  42. AmtEkb:

    да, именно 🙂

  43. Kr0Blank:

    А вот на ЛИСПе это решается в один момент… 😀

  44. PeeZlo:

    Можно прогонять свой код через какой-нибудь макропроцессор. Это немного извращение и издевательство в случае, если кто-то кроме тебя потом этот проект поддерживать захочет, но взамен дает некоторое количество клевых возможностей, включая вариацию «#ifdef debug».

    Я когда-то в таком контексте поверх Явы M4 прикручивал бывало — было забавно.

  45. KenGood:

    на каком диалекте?

  46. Kr0Blank:

    CL или Clojure.

  47. Nelef:

    Я так думаю, что автору тогда и код вообще не стоит писать. Пустая программа будет исполняться моментально! Гигантский выигрыш производительности!

  48. XibZZ:

    о, а я ведь, кстати, делал для похапе-фреймворка собиралку большой такой кучи.php файлов в один (что дает заметное преимущество по времени инициализации при наличии опкод кэшера, но возможно, конечно, только при соблюдении определенных coding conventions). Разбирается с зависимостями через адскую смесь токенайзера и reflection. Прикрутить туда простейший макропроцессор — элементарно, особенно, если вынести его директивы в phpdoc-комментарии 🙂

  49. AmtEkb:

    выше уже про это говорили, только в терминах «препроцессор» 🙂

  50. PeeZlo:

    Ну там что-то предлагали про «написать препроцессор» что немного издевательство.
    А взять готовый макропроцессор — вполне комильфо. Только вот дефакто гну-стандартный M4 это какой-то страх и ужас в плане синтаксиса, использование CPP поверх пхп как-то религиозно неправильно, а кроме этих двух ничего в голову и не приходит. Знает здесь кто-нибудь красивый и удобный general-purpose макропроцессор вообще?

  51. Xuagreen:

    препроцессоры используются только недоразвитыми языками.

  52. PeeZlo:

    Препроцессор можно прикрутить куда угодно, так как он — вершина пищевой цепи языков программирования.

  53. Xuagreen:

    препроцессор нужен тогда, когда язык не справляется с поставленными задачами, то есть язык — говно.

  54. PeeZlo:

    Задач может быть поставлено много. Языки, которые пытаются решать все задачи сразу — говно.

  55. AmtEkb:

    команды препроцессора можно включить в синтаксис языка и назвать новый язык как старый с тремя плюсами 🙂 Будет язык-неговно!

  56. Xuagreen:

    угу, поэтому разные языки решают разные задачи. А языки с препроцессорами — говно, потому что ни со своими задачами не справляются, ни с дополнительными.

  57. AmtEkb:

    Ну вот более-менее красивый вариант, который я подглядел в джумле:

    define(DEBUG_LEVEL_1, $curLogLevel > 0);
    define(DEBUG_LEVEL_2, $curLogLevel > 1);

    DEBUG_LEVEL_1? log(«blah-blah-blah») : 0;

    DEBUG_LEVEL_2? log(«blah2-blah2-blah2») : 0;

    Тут хотя бы нет вызова функции, и проверка не выглядит уёбищно (ну хотя кому как, конечно).

  58. PeeZlo:

    Да нет уж. Учитывая что у препроцессора и у языка программирования разные задачи, то язык без препроцессора просто не способен выполнять те задачи, которые способен выполнять язык с препроцессором.
    А говно — это Руби.

  59. Eheko:

    пиши на си компили.so

Добавить комментарий