В тот день, когда я занимался программированием на С, мы использовали операторы предположения, чтобы убедиться, что код исправен. Что-то вроде:
aFunction(int hello)
{
assume(hello < 10);
Крутая вещь в операторе предположения состоит в том, что он определен как пустой макрос для компиляции релиза и оператор die on false при компиляции отладки. Таким образом, разработчик имел все преимущества оператора assert, который проверял свои предположения, не вызывая ненужных ошибок и не влияя на производительность.
Теперь, когда я работаю с php, я ищу похожий механизм. В настоящее время мое предположение выглядит примерно так:
define(DEBUG, getenv('debug'));
function assume($a)
{
if (DEBUG && !$a)
{
echo 'ASSUME FAILURE <br />';
echo '<pre>';
print_r(debug_backtrace());
die('<pre>');
}
}
assume($a == $b);
Как вы можете видеть, я установил флаг отладки в настройках сервера, чтобы удалить фактический оператор die и тому подобное. Однако вызов функции все еще выполняется, и оператор if все еще оценивается. Это не имеет большого значения, если это происходит всего несколько тысяч раз, но, когда код становится больше, а поскольку предполагается, что он зацикливается, это может оказать законное влияние на производительность.
Есть ли способ сказать интерпретатору или opcache (в настоящее время я использую zend opcache, включенный в php 5.5), чтобы вообще игнорировать эти операторы предположения? или есть другой способ решения этой проблемы?
Разница в том, что компилятор C оптимизирован и может исключать блоки кода, которые не используются. В PHP assume
это вызов функции, и функция должна существовать.
Пара решений. Во-первых, вы можете использовать assert()
. assert
функция работает аналогично вашей assume
функция. Если утверждение не выполняется, вызывается определенный обработчик подтверждения. Вы можете легко включить или отключить утверждения, и если вы их отключите, обработчик утверждений вообще не вызывается.
Если вы хотите продолжить свой собственный assume
функцию, вы все еще можете немного оптимизировать ее, объявив функцию на основе define:
<?php
define(DEBUG, getenv('debug'));
if (DEBUG) {
function assume($a) {
echo 'ASSUME FAILURE <br />';
echo '<pre>';
echo print_r(debug_backtrace());
die('<pre>');
}
} else {
function assume($x) {}
}
Таким образом, вы на самом деле объявляете assume
как пустая функция. Комментарий Майкла Берковски подтверждает мой страх, что PHP не устраняет вызов полностью, но, по крайней мере, вы сохраняете if
,
Другое решение состоит в том, чтобы назвать предположения немного более сложным:
DEBUG && assume($x < 10);
Таким образом, если DEBUG имеет значение false, вызов не выполняется вообще. Таким образом, оценивается только логическое значение, и вызов функции не выполняется. Конечно, назвать его таким образом немного сложнее и менее читабельно, но я думаю, что экономия от не вызова функции гораздо важнее, чем устранение if
,
Других решений пока нет …