Я работаю над системой обработки событий в реальном времени. Я хотел бы свести к минимуму столько вызовов в моем коде, которые имеют недетерминированную синхронизацию. Мне нужно создать сообщение, которое состоит из строк, чисел, меток времени и GUID. Вероятно, std::vector
из boost::variant
.
Я всегда хотел использовать alloca
в прошлом коде аналогичного характера. Однако, когда кто-то изучает системное программирование, всегда есть серьезные предостережения против этого вызова функции. Лично я не могу думать о машине серверного класса за последние 15 лет, у которой нет виртуальной памяти, и я точно знаю, что стек Windows увеличивает виртуальную память на странице за раз, поэтому я предполагаю, Юниты тоже так делают. Здесь больше нет кирпичной стены, стек, скорее всего, исчерпает пространство так же, как и куча, так что дает? Почему люди не выходят из-под алока? Я могу вспомнить множество вариантов использования ответственного использования alloca (кто-нибудь обрабатывает строки?).
Во всяком случае, я решил проверить разницу в производительности (см. Ниже), и есть 5-кратная разница в скорости между alloca и malloc (тест фиксирует, как я буду использовать alloca). Итак, все изменилось? Должны ли мы просто проявить осторожность и использовать alloca
(завернутый в std::allocator
) всякий раз, когда мы можем быть абсолютно уверены в сроке службы наших объектов?
Я устал жить в страхе!
Edit:
Хорошо, существуют ограничения, для окон это ограничение времени соединения. Для Unix это кажется настраиваемым. Кажется, что распределитель памяти с выравниванием по страницам находится в порядке: D Кто-нибудь знает о переносимой реализации общего назначения: D?
Код:
#include <stdlib.h>
#include <time.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace boost::posix_time;
int random_string_size()
{
return ( (rand() % 1023) +1 );
}
int random_vector_size()
{
return ( (rand() % 31) +1);
}
void alloca_test()
{
int vec_sz = random_vector_size();
void ** vec = (void **) alloca(vec_sz * sizeof(void *));
for(int i = 0 ; i < vec_sz ; i++)
{
vec[i] = alloca(random_string_size());
}
}
void malloc_test()
{
int vec_sz = random_vector_size();
void ** vec = (void **) malloc(vec_sz * sizeof(void *));
for(int i = 0 ; i < vec_sz ; i++)
{
vec[i] = malloc(random_string_size());
}
for(int i = 0 ; i < vec_sz ; i++)
{
free(vec[i]);
}
free(vec);
}
int main()
{
srand( time(NULL) );
ptime now;
ptime after;
int test_repeat = 100;
int times = 100000;
time_duration alloc_total;
for(int ii=0; ii < test_repeat; ++ii)
{
now = microsec_clock::local_time();
for(int i =0 ; i < times ; ++i)
{
alloca_test();
}
after = microsec_clock::local_time();
alloc_total += after -now;
}
std::cout << "alloca_time: " << alloc_total/test_repeat << std::endl;
time_duration malloc_total;
for(int ii=0; ii < test_repeat; ++ii)
{
now = microsec_clock::local_time();
for(int i =0 ; i < times ; ++i)
{
malloc_test();
}
after = microsec_clock::local_time();
malloc_total += after-now;
}
std::cout << "malloc_time: " << malloc_total/test_repeat << std::endl;
}
выход:
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056302
malloc_time: 00:00:00.260059
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056229
malloc_time: 00:00:00.256374
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056119
malloc_time: 00:00:00.265731
- Изменить: Результаты на домашнем компьютере, Clang и Google perftools -
G++ without any optimization flags
alloca_time: 00:00:00.025785
malloc_time: 00:00:00.106345
G++ -O3
alloca_time: 00:00:00.021838
cmalloc_time: 00:00:00.111039
Clang no flags
alloca_time: 00:00:00.025503
malloc_time: 00:00:00.104551
Clang -O3 (alloca become magically faster)
alloca_time: 00:00:00.013028
malloc_time: 00:00:00.101729
g++ -O3 perftools
alloca_time: 00:00:00.021137
malloc_time: 00:00:00.043913
clang++ -O3 perftools (The sweet spot)
alloca_time: 00:00:00.013969
malloc_time: 00:00:00.044468