смешивание суда и printf для более быстрого вывода

Для Firebase Hosting документация по переадресации и перезаписи приведена здесь: https://www.firebase.com/docs/hosting/guide/url-redirects-rewrites.html

Оттуда:

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

blockquote>

Вероятно, вы ищете первый переписать sample на этой странице:

rewrites": [ {
  "source": "**",
  "destination": "/index.html"
} ]

Это инструкция для веб-сервера, которая будет обслуживать /index.html для любого входящего запроса, независимо от того, какой путь.

48
задан Jabba 18 December 2009 в 19:52
поделиться

9 ответов

Прямой ответ - да, это нормально.

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

#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>

char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";

void show_time(void (*f)(), char const *caption) { 
    clock_t start = clock();
    f();
    clock_t ticks = clock()-start;
    std::cerr << std::setw(30) << caption 
        << ": " 
        << (double)ticks/CLOCKS_PER_SEC << "\n";
}

void use_printf() {
    for (int i=0; i<count; i++)
        printf(fmt, string);
}

void use_puts() {
    for (int i=0; i<count; i++) 
        puts(string);        
}

void use_cout() { 
    for (int i=0; i<count; i++)
        std::cout << string << "\n";
}

void use_cout_unsync() { 
    std::cout.sync_with_stdio(false);
    for (int i=0; i<count; i++)
        std::cout << string << "\n";
    std::cout.sync_with_stdio(true);
}

void use_stringstream() { 
    std::stringstream temp;
    for (int i=0; i<count; i++)
        temp << string << "\n";
    std::cout << temp.str();
}

void use_endl() { 
    for (int i=0; i<count; i++)
        std::cout << string << std::endl;
}

void use_fill_n() { 
    std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}

void use_write() {
    for (int i = 0; i < count; i++)
        std::cout.write(s.data(), s.size());
}

int main() { 
    show_time(use_printf, "Time using printf");
    show_time(use_puts, "Time using puts");
    show_time(use_cout, "Time using cout (synced)");
    show_time(use_cout_unsync, "Time using cout (un-synced)");
    show_time(use_stringstream, "Time using stringstream");
    show_time(use_endl, "Time using endl");
    show_time(use_fill_n, "Time using fill_n");
    show_time(use_write, "Time using write");
    return 0;
}

Я запускал ее в Windows после компиляции с VC ++ 2013 (как x86, так и x64 версии). Результат одного прогона (с перенаправлением вывода в файл на диске) выглядел следующим образом:

          Time using printf: 0.953
            Time using puts: 0.567
   Time using cout (synced): 0.736
Time using cout (un-synced): 0.714
    Time using stringstream: 0.725
            Time using endl: 20.097
          Time using fill_n: 0.749
           Time using write: 0.499

Как и ожидалось, результаты различаются, но есть несколько моментов, которые я нашел интересными:

  1. printf / put намного быстрее, чем cout при записи в устройство NUL
    • , но cout неплохо справляется с записью в настоящий файл
  2. Многие предлагаемые оптимизации мало что дают
    • В моем тестировании fill_n примерно так же быстро, как и все остальное
  3. Безусловно, самая большая оптимизация - избегание endl
  4. cout.write показало самое быстрое время (хотя, вероятно, не с большим отрывом

Я недавно отредактировал код, чтобы принудительно вызвать printf . Андерс Касеорг любезно указал, что g ++ распознает конкретную последовательность printf ("% s \ n" , foo); эквивалентно put (foo); и соответственно генерирует код (т. е. генерирует код для вызова put вместо printf ) .Перенос строки формата в глобальный массив и передача ее в качестве строки формата дает идентичный вывод, но заставляет его генерировать через printf вместо put . Конечно, это 'Возможно, когда-нибудь они тоже смогут оптимизировать это, но, по крайней мере, на данный момент (g ++ 5.1) тест с g ++ -O3 -S подтверждает, что он действительно вызывает printf (где предыдущий код, скомпилированный для вызова , помещает ).

69
ответ дан 7 November 2019 в 12:11
поделиться

Ну, я не могу придумать никакой причины для использования cout Если честно. Совершенно безумно иметь огромный громоздкий шаблон для чего-то настолько простого, что будет в каждом файле. Кроме того, похоже, что он разработан так, чтобы печатать как можно медленнее, и после миллионного раза ввода <<<<, а затем ввода значения между ними и случайного получения чего-то lik> variableName >>> Я больше не хочу этого делать .

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

Однако мне тоже не очень нравится printf. Для меня, решение состоит в том, чтобы создать свой собственный конкретный класс, а затем вызвать в нем все, что необходимо для io. Тогда у вас может быть действительно простой io любым способом и с любой реализацией, которую вы хотите, с любым форматированием, которое вы хотите, и т.д. (обычно вы хотите, чтобы числа с плавающей запятой всегда были односторонними, например, а не форматировали их 800 способов без причины, поэтому поместите в форматировании при каждом звонке - это шутка).

Так что все, что я печатаю, это что-то вроде dout + "Это более разумно, чем" + cPlusPlusMethod + "из" + debugIoType + ". По крайней мере, IMO"; dout ++;

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

Кроме того, нет ничего плохого в смешивании C и C ++, это должно быть сделано разумно, и если вы используете вещи, которые вызывают проблемы с использованием C в Во-первых, можно с уверенностью сказать, что меньше всего вас беспокоят проблемы, связанные с смешиванием C и C ++.

1
ответ дан 7 November 2019 в 12:11
поделиться

Не беспокойтесь о производительности между printf и cout . Если вы хотите повысить производительность, отделите форматированный вывод от неформатированного.

put ("Hello World \ n") намного быстрее, чем printf ("% s", "Hellow World \ n") . (В первую очередь из-за накладных расходов на форматирование). После того, как вы изолировали форматированный текст от обычного текста, вы можете использовать такие приемы, как:

const char hello[] = "Hello World\n";
cout.write(hello, sizeof(hello) - sizeof('\0'));

Чтобы ускорить форматированный вывод, хитрость заключается в том, чтобы выполнить все форматирование в строку, а затем использовать вывод блока со строкой (или буфером):

const unsigned int MAX_BUFFER_SIZE = 256;
char buffer[MAX_BUFFER_SIZE];
sprintf(buffer, "%d times is a charm.\n", 5);
unsigned int text_length = strlen(buffer) - sizeof('\0');
fwrite(buffer, 1, text_length, stdout);

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

3
ответ дан 7 November 2019 в 12:11
поделиться

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

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

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

  • несинхронизировать ввод-вывод C ++ с CI / O (см. Sync_with_stdio ()).
  • Убедитесь, что количество сбросов сопоставимо.
12
ответ дан 7 November 2019 в 12:11
поделиться

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

setvbuf (stdout, NULL, _IOFBF, 32768);  // any value larger than 512 and also a
                  // a multiple of the system i/o buffer size is an improvement

Количество обращений к операционной системе для выполнение ввода-вывода почти всегда является самым дорогим компонентом и ограничителем производительности.

Конечно, если вывод cout смешивается с stdout , очистка буфера не справляется с этой целью увеличение буфера размер.

9
ответ дан 7 November 2019 в 12:11
поделиться

Вы можете использовать sync_with_stdio , чтобы ускорить ввод-вывод C ++.

cout.sync_with_stdio(false);

Должен улучшить производительность вывода с помощью cout .

5
ответ дан 7 November 2019 в 12:11
поделиться

Мои книги по C ++ рекомендовали не смешивать методы C ++ и C, к сведению. Я почти уверен, что функции C нарушают состояние, ожидаемое / удерживаемое C ++.

0
ответ дан 7 November 2019 в 12:11
поделиться

Отправка std::endl в поток добавляет newline и смывает поток. Последующее обращение к cout.flush() является излишним. Если это было сделано при синхронизации cout с printf, то вы не сравнивали яблоки с яблоками.

.
19
ответ дан 7 November 2019 в 12:11
поделиться

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

12
ответ дан 7 November 2019 в 22:11
поделиться
Другие вопросы по тегам:

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