Значения производительности массива переменной длины (C/C++)
Я пишу довольно простую функцию, которая отправляет массив в дескриптор файла. Однако для отправки данных мне нужно добавить однобайтовый заголовок.
Вот упрощенная версия того, что я делаю, и кажется, что это работает:
void SendData(uint8_t* buffer, size_t length) {
uint8_t buffer_to_send[length + 1];
buffer_to_send[0] = MY_SPECIAL_BYTE;
memcpy(buffer_to_send + 1, buffer, length);
// more code to send the buffer_to_send goes here...
}
Как я уже сказал, код, кажется, работает нормально, однако, недавно я приобрел привычку использовать руководство по стилю Google C++, так как в моем текущем проекте нет руководства по заданным стилям (на самом деле я единственный разработчик программного обеспечения в моем проект, и я хотел использовать то, что используется в промышленности). Я запустил Google cpplint.py, и он поймал строку, где я создаю buffer_to_send, и бросил некоторые комментарии о том, что я не использую массивы переменной длины. В частности, вот что говорит руководство по стилю Google C++ о массивах переменной длины...
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Variable-Length_Arrays_and_alloca__
Судя по их комментариям, я обнаружил причину случайных сбоев в моем коде (которые происходят очень редко, но, тем не менее, раздражают). Тем не менее, я немного расстроен тем, как это исправить.
Вот мои предложенные решения:
Сделайте buffer_to_send по существу массивом фиксированной длины постоянной длины. Проблема, о которой я могу подумать, заключается в том, что я должен сделать буфер таким же большим, как теоретически самый большой буфер, который я хочу отправить. В среднем случае буферы намного меньше, и я бы потратил около 0,5 КБ, делая это каждый раз, когда вызывается функция. Обратите внимание, что программа должна работать во встроенной системе, и хотя я не обязательно считаю каждый байт, я бы хотел использовать как можно меньше памяти.
Используйте new и delete или malloc/free для динамического выделения буфера. Проблема здесь в том, что функция вызывается часто, и могут возникнуть некоторые проблемы, связанные с постоянным запросом памяти у ОС и последующим ее освобождением.
Используйте два последовательных вызова write() для передачи данных в файловый дескриптор. Таким образом, первая запись будет передавать только один байт, а следующая будет отправлять оставшуюся часть буфера. На первый взгляд, мне нужно немного больше исследовать код (обратите внимание, что я получил этот код от предыдущего инженера, который с тех пор покинул компанию, в которой я работаю), чтобы гарантировать, что две последовательные записи происходят атомарно. Кроме того, если для этого требуется блокировка, то она существенно усложняется и оказывает большее влияние на производительность, чем случай №2.
Обратите внимание, что я не могу сделать buffer_to_send переменной-членом или ограничить ее область за пределами функции, поскольку в любой момент времени (потенциально) в функцию поступают несколько вызовов из различных потоков.
Пожалуйста, дайте мне знать ваше мнение и какой мой предпочтительный подход должен быть. Спасибо за ваше время.
2 ответа
Вы можете сложить два последовательных вызова write() в вашем варианте 3 в один вызов с помощью writev ().
http://pubs.opengroup.org/onlinepubs/009696799/functions/writev.html
Я бы выбрал вариант 1. Если вы знаете максимальную длину ваших данных, выделите столько стека (плюс один байт) в стеке, используя массив фиксированного размера. Это не хуже, чем у массива переменной длины, который вы показали, потому что у вас всегда должно быть достаточно места в стеке, иначе вы просто не сможете обработать вашу максимальную длину (в худшем случае ваш код будет случайно зависать при больших размерах буфера), Во время вызова этой функции ничто другое не будет использовать дополнительное пространство в вашем стеке, поэтому будет безопасно выделить массив фиксированного размера.