Как очистить записи кэша APC?

На этот вопрос уже был дан ответ, но я думаю, что стоит углубиться во все возможные варианты выхода из цикла в c ++. Существует в основном пять возможностей:

  • Использование условия цикла
  • Использование условия break
  • Использование условия return
  • Использование исключения
  • Использование goto

Далее я опишу варианты использования этих опций с использованием c ++ 14. Однако вы можете делать все это в более ранних версиях c ++ (за исключением, возможно, исключений). Короче говоря, я опущу функции include и main. Пожалуйста, прокомментируйте, если вы считаете, что какая-то часть нуждается в большей ясности.

1. Использование условия цикла

Стандартным способом выхода из цикла является условие цикла. Условие цикла записывается в средней части оператора for или в скобках оператора while:

for(something; LOOP CONDITION; something) {
    ... 
}
while (LOOP CONDITION)
    ... 
}
do {
    ... 
} while (LOOP CONDITION);

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

Например, если мы хотим вывести число от 0 до 2, мы могли бы написать код, используя цикл и условие цикла:

for (auto i = 0; i <= 2; ++i)
    std::cout << i << '\n';
std::cout << "done";

Здесь условие - i <= 2. Пока это условие оценивается как true, цикл продолжает работать.

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

auto condition = false;

for (auto i = 0; !condition; ++i) {
    std::cout << i << '\n';
    condition = i > 2;
}
std::cout << "done";

Проверяя вывод для обеих версий, мы получаем желаемый результат:

0
1
2
done

Как бы вы использовали условие цикла в реальном приложении?

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

Например:

auto condition = false;
for (auto i = 0; !condition; ++i)
    if (is_prime(i))
        if (is_large_enough(i)) {
            key = calculate_cryptographic_key(i, data);
            if (is_good_cryptographic_key(key))
                condition = true;
        }

2. Использование условия break

Другой простой способ выйти из цикла - использовать ключевое слово break. Если он используется внутри цикла, выполнение остановится и продолжится после тела цикла:

for (auto i = 0; true; ++i) {
    if (i == 3)
        break;
    std::cout << i << '\n';
}
std::cout << "done";

Это выведет текущее число и увеличит его на единицу, пока i не достигнет значения 3. Здесь утверждение if является нашим условием break. Если условие true, цикл прерывается (обратите внимание на !), и выполнение продолжается со следующей строки, печатающей done.

Выполняя тест, мы действительно получаем ожидаемый результат:

0
1
2
done

Важно, что это остановит только самый внутренний цикл в коде. Поэтому, если вы используете несколько циклов, это может привести к нежелательному поведению:

for (auto j = 0; true; ++j)
    for (auto i = 0; true; ++i) {
        if (i == 3)
            break;
        std::cout << i << '\n';
    }
std::cout << "done";

С помощью этого кода мы хотели получить тот же результат, что и в примере выше, но вместо этого мы получаем бесконечный цикл, потому что break останавливает цикл только над i, а не цикл j!

Выполнение теста:

0
1
2
0
1
2
...

Как бы вы использовали break ] условие в реальном приложении?

Обычно break используется только для пропуска частей внутреннего цикла или для добавления дополнительного выхода из цикла.

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

auto is_prime = true;
for (auto i = 0; i < p; ++i) {
    if (p%i == 0) { //p is dividable by i!
        is_prime = false;
        break; //we already know that p is not prime, therefore we do not need to test more cases!
    }

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

auto j = size_t(0);
for (auto i = size_t(0); i < data.size(); ++i)
    if (data[i] == "Hello") { //we found "Hello"!
        j = i;
        break; //we already found the string, no need to search any further!
    }

3. Использование условия return

Ключевое слово return выходит из текущей области и возвращается к вызывающей функции. Таким образом, его можно использовать для выхода из цикла и, кроме того, для возврата номера вызывающей стороне. Распространенным случаем является использование return для выхода из цикла (и его функции) и возврата результата.

Например, мы можем переписать функцию is_prime сверху:

auto inline is_prime(int p) {
    for (auto i = 0; i < p; ++i)
        if (p%i == 0) //p is dividable by i!
            return false; //we already know that p is not prime, and can skip the rest of the cases and return the result
    return true; //we didn't find any divisor before, thus p must be prime!
}

Ключевое слово return также можно использовать для выхода из нескольких циклов:

auto inline data_has_match(std::vector<std::string> a, std::vector<std::string> b) {
    for (auto i = size_t(0); i < a.size(); ++i)
        for (auto j = size_t(0); j < a.size(); ++j)
            if (a[i] == b[j])
                return true; //we found a match! nothing to do here
    return false; //no match was found
}

Как бы вы использовали условие return в реальном приложении?

Внутри небольших функций return часто используется для выхода из циклов и напрямую вернуть результаты. Кроме того, внутри больших функций return помогает сохранять код понятным и читабельным:

for (auto i = 0; i < data.size(); ++i) {
    //do some calculations on the data using only i and put them inside result
    if (is_match(result,test))
        return result;
    for (auto j = 0; j < i; ++j) {
        //do some calculations on the data using i and j and put them inside result
        if (is_match(result,test))
            return result;
    }
}
return 0; //we need to return something in the case that no match was found

Что гораздо легче понять, чем:

auto break_i_loop = false;
auto return_value = 0;
for (auto i = 0; !break_i_loop; ++i) {
    //do some calculations on the data using only i and put them inside result
    if (is_match(result,test)) { //a match was found, save the result and break the loop!
        return_value = result;
        break;
    }
    for (auto j = 0; j < i; ++j) {
        //do some calculations on the data using i and j and put them inside result
        if (is_match(result,test)) { //a match was found, save the result, break the loop, and make sure that we break the outer loop too!
            return_value = result;
            break_i_loop = true;
            break;
        }
    }
    if (!break_i_loop) //if we didn't find a match, but reached the end of the data, we need to break the outer loop
        break_i_loop = i >= data.size();
}
return return_value; //return the result

4. Использование исключений

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

Как бы вы использовали исключение в реальном приложении?

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

auto inline inverse_data(std::vector<int>& data) {
    for (auto i = size_t(0); i < data.size(); ++i)
        if (data[i] == 0)
            throw std::string("Division by zero on element ") + std::to_string(i) + "!";
        else
            data[i] = 1 / data[i];
}

Мы можем обработать это исключение внутри вызывающей функции:

while (true)
    try {
        auto data = get_user_input();
        inverse = inverse_data(data);
        break;
    }
    catch (...) {
        std::cout << "Please do not put zeros into the data!";
    }

Если data содержит ноль, то inverse_data выдает исключение, break никогда не выполняется, и пользователь должен снова вводить данные.

Есть еще больше опций для такого рода обработки ошибок, с дополнительными типами ошибок, ..., но это тема для другого дня.

** Что вы никогда не должны делать! **

Как упоминалось ранее, исключения могут привести к значительным накладным расходам во время выполнения. Поэтому их следует использовать только в действительно исключительных случаях. Хотя можно написать следующую функцию, не надо!

auto inline next_prime(int start) {
    auto p = start;
    try {
        for (auto i = start; true; ++i)
            if (is_prime(i)) {
                p = i;
                throw;
            }
   }
   catch (...) {}
   return p;
 }

5. Использование goto

Ключевое слово goto ненавидимо большинством программистов, потому что оно затрудняет чтение кода и может иметь непредвиденные побочные эффекты. Однако его можно использовать для выхода из (нескольких) циклов:

for (auto j = 0; true; ++j)
    for (auto i = 0; true; ++i) {
        if (i == 3)
            goto endloop;
        std::cout << i << '\n';
    }
endloop:
std::cout << "done";

Этот цикл закончится (не как цикл в части 2) и выдает:

0
1
2
done

Как бы вы использовали goto в реальных приложениях?

В 99,9% случаев нет необходимости использовать ключевое слово goto. Единственным исключением являются встроенные системы, такие как Arduino, или код с очень высокой производительностью. Если вы работаете с одним из этих двух, вы можете использовать goto для создания более быстрого или более эффективного кода. Тем не менее, для обычного программиста, недостатки намного больше, чем выгоды от использования goto.

Даже если вы считаете, что ваш случай составляет один из 0,1%, вам нужно проверить, действительно ли goto улучшает ваше исполнение. Чаще всего использование условия break или return происходит быстрее, потому что компилятору сложно понять код, содержащий goto.

171
задан lo_fye 26 May 2009 в 15:00
поделиться

4 ответа

Fiddler 2 - отличный инструмент для наблюдения за HTTP-трафиком.

* Обновление 2014 г. *

Начиная с моего исходного сообщения, и Internet Explorer, и Chrome добавили встроенного разработчика инструменты, которые весьма полезны. Хотя я по-прежнему поддерживаю и использую Fiddler для HTTP-мониторинга, не связанного с сетью, или когда мне нужно действительно копаться в деталях и изменять запросы в пути, в наши дни я в значительной степени использую встроенные инструменты IE или Chrome, поскольку их достаточно для 99% моих потребностей. У них обоих есть вкладка сети, где вы можете отслеживать HTTP-запросы, а также другие полезные функции для отладки веб-страниц.

145
ответ дан 23 November 2019 в 20:43
поделиться

Это не указано в документации, но для очистки кеша опкодов вы должны сделать:

apc_clear_cache('opcode');

РЕДАКТИРОВАТЬ: Кажется, это применимо только к некоторым более старым версиям APC ..

Независимо от того, какую версию вы используете не может очистить кеш APC mod_php или fastcgi из сценария php cli, поскольку сценарий cli будет запускаться из другого процесса как mod_php или fastcgi. Вы должны вызвать apc_clear_cache () из процесса (или дочернего процесса), для которого вы хотите очистить кеш. Одним из таких подходов является использование curl для запуска простого скрипта php.

29
ответ дан 23 November 2019 в 20:43
поделиться

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

-1
ответ дан 23 November 2019 в 20:43
поделиться

Я не верю, что какой-либо из этих ответов действительно работает для очистки кэша APC из командной строки. Как Frank Farmer прокомментировал выше, CLI работает в процессе, отдельном от Apache.

Моим решением для очистки из командной строки было написать сценарий, который копирует сценарий очистки APC в каталог web, обращается к нему и затем удаляет его. Доступ к сценарию ограничен с локального хоста.

  1. apc_clear.php

    Это файл, который скрипт копирует в веб-каталог, открывает и удаляет.

     правда));
    }
    еще
    {
    die('СОВЕРШЕННО СЕКРЕТНО');
    }
    
  2. Скрипт очистки кеша

    Этот скрипт копирует apc_clear.php в веб-каталог, обращается к нему, а затем удаляет его. Это основано на задаче Symfony. В версии Symfony обращения к форме Symfony для копирования и разъединения выполняются, которые обрабатывают ошибки. Вы можете добавить проверки, что они успешны.

    copy($apcPaths['data'], $apcPaths['web']); //'data' - это каталог, недоступный из Интернета
    
    $url = 'http://localhost/apc_clear.php'; // используем доменное имя по мере необходимости
    $result = json_decode(file_get_contents($url));
    если (isset($result['успех']) && $result['success'])
    {
     //обработка успеха
    }
    еще
    {
     //обработка отказа
    }
    развязать($apcPaths['Интернет']);
    
115
ответ дан 23 November 2019 в 20:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: