Быстрее всего можно выделить массив строк - PullRequest
1 голос
/ 06 октября 2011

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

temp = (char**) realloc (buffer, newSize * (sizeof(char*)));
if (temp == NULL)
    return false;
else
    buffer = temp;

И пока все хорошо. Теперь для каждой новой ячейки я должен вызывать malloc с правильным размером. Обратите внимание, что newSize всегда четный и длина нечетных строк отличается от четных.

for (i = oldSize; i < newSize; i++){
    support = (char*) malloc (LENGTH1 * sizeof(char));
    if (support == NULL){
        marker = i;
        failedMalloc = true;
        break;
    }
    else
        buffer[i] = support;

    i++;

    support = (char*) malloc (LENGTH2 * sizeof(char));
    if (support == NULL){
        marker = i;
        failedMalloc = true;
        break;
    }
    else
        buffer[i] = support;

}

Дело в том, что, так как я рано или поздно работаю с большими данными, я закончу память, и realloc или один из mallocs потерпит неудачу. Проблема в том, что, если это один из malloc, который выходит из строя, есть риск, что мне придется вызвать миллионов бесплатно, чтобы очистить часть памяти. Это занимает много времени. Есть ли способ ускорить этот процесс или даже лучше его избежать?

if (failedMalloc){
    for (i = oldRows; i < marker; i++)
        free(buffer[i]);
    temp = (char**) realloc (buffer, oldRows * (sizeof(char*)));
}

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

Ответы [ 4 ]

4 голосов
/ 06 октября 2011

Вместо того, чтобы выделять каждую строку индивидуально, размещайте их в блоках.Вы можете, например, malloc 128 * (LENGTH1 + LENGTH2) и иметь место для 256 последовательных строк.Всякий раз, когда ваш индекс пересекает границу блока, malloc другой большой блок и использовать арифметику по модулю, чтобы получить смещение в нем для начала строки.

PS sizeof (char) гарантированно будет равен 1.

1 голос
/ 06 октября 2011

Выделите большие блоки памяти. Чем меньше вызовов malloc, тем лучше. Самым быстрым будет предварительный расчет необходимого размера и его распределение только один раз.

Кроме того, использование арифметики с указателями здесь не даст никакой видимой разницы.

0 голосов
/ 06 октября 2011

Один из способов избежать неэффективного использования памяти состоит в том, чтобы каждый раз выделять больший объем памяти, когда вам нужно malloc,

фиксированный размер malloc (выравнивание по 2 ^ n), например

int m_size = 1;

// when need malloc
while (m_size < require_size) m_size * 2;
malloc(m_size);
0 голосов
/ 06 октября 2011

Вы можете написать свои собственные процедуры размещения и освобождения и использовать их вместо malloc/free для строк.Если ваша подпрограмма malloc содержит один или несколько больших буферов и разбивает их на части, то вы можете освободить весь лот за один раз, просто вызвав free для каждого большого буфера.

Общая идея работаетособенно хорошо в случае, когда все распределения имеют одинаковый размер, и в этом случае это называется «распределителем пула».В этом случае для каждого массива или строк у вас может быть один связанный пул для выделений LENGTH1, а другой для LENGTH2.

Я говорю «напишите свое», но, без сомнения, естьпростые распределители пулов с открытым исходным кодом для принятия.

...