Эффективное чтение стандартного программирования - PullRequest
2 голосов
/ 12 апреля 2011

Может кто-нибудь помочь мне оптимизировать код для чтения стандартного ввода. Вот что у меня сейчас:

unsigned char *msg;
size_t msgBytes = 0;
size_t inputMsgBuffLen = 1024;
if ( (msg = (unsigned char *) malloc(sizeof(unsigned char) * inputMsgBuffLen) ) == NULL ) {
    quitErr("Couldn't allocate memmory!", EXIT_FAILURE);
}
for (int c; (c = getchar()) != EOF; msgBytes++) {
    if (msgBytes >= (inputMsgBuffLen)) {
        inputMsgBuffLen <<= 1;
        if ( ( msg = (unsigned char *)realloc(msg, sizeof(unsigned char) * inputMsgBuffLen) ) == NULL) {
            free(msg);
            quitErr("Couldn't allocate more memmory!", EXIT_FAILURE);
        }
    }
    msg[msgBytes] = (unsigned char)c;
}

Ответы [ 3 ]

5 голосов
/ 12 апреля 2011

Вопрос: вы читаете двоичные или текстовые данные из stdin? Если текст, почему вы используете unsigned char?

Несколько советов:

  1. Отбросьте все приведения на malloc и realloc; они не нужны и загромождают код;
  2. Вместо многократного вызова getchar используйте fread или fgets (в зависимости от того, читаете ли вы двоичный или текстовый текст);
  3. Помните, что realloc потенциально может возвращать NULL, поэтому вы хотите присвоить результат временному значению, иначе вы потеряете исходный указатель и потеряете память;
  4. Использовать статически распределенный буфер для каждого блока ввода;
  5. Используйте sizeof на объектах, а не на типах; он немного чище и защищает вас в случае смены типа (например, T *p = malloc(sizeof *p * number_of_elements);.

Исправленная версия, предполагающая, что вы собираетесь использовать неподписанные символы:

#define inputBufSize 1024

unsigned char *msg = NULL;
size_t msgBytes = 0;
size_t inputMsgBufSize = 0;
unsigned char inputBuffer[inputBufSize];
size_t bytesRead = 0;

while ((bytesRead = fread(
    inputBuffer,            // target buffer
    sizeof inputBuffer,     // number of bytes in buffer
    1,                      // number of buffer-sized elements to read
    stdin)) > 0)
{
  unsigned char *tmp = realloc(msg, inputMsgBufSize + bytesRead));
  if (tmp)
  {
    msg = tmp;
    memmove(&msg[inputMsgBufSize], inputBuffer, bytesRead);
    inputMsgBufSize += bytesRead;
  }
  else
  {
    printf("Ran out of memory\n");
    free(msg);
    break;
  }
}
2 голосов
/ 12 апреля 2011

Попробуйте прочитать фиксированные блоки размером не менее 8192 байт.Не используйте ввод с одним символом, поскольку он довольно медленный.

0 голосов
/ 12 апреля 2011

Почему вы хотите «оптимизировать» код?

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

Лучшая оптимизация, которую вы можете сделать, - это начать с очень большого значения для malloc (и, возможно, realloc вниз после того, как все данные будут прочитаны).

size_t inputMsgBuffLen = 400000000; /* approx 400 mega */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...