этот код может быть оптимизирован? - PullRequest
1 голос
/ 22 августа 2011

Я думаю, что я одержим оптимизацией, поэтому мне интересно, что следующий код можно «оптимизировать»:

Допустим, у меня есть связанный список языков C, и при создании нового элемента я использую этоткод:

log_event_list_cur->next = 
    (struct log_event_list *)malloc(sizeof(struct log_event_list));

log_event_list_cur = log_event_list_cur->next;

Интересно, будет ли следующий код в порядке:

log_event_list_cur = 
    log_event_list_cur->next = 
        (struct log_event_list *) malloc(sizeof(struct log_event_list));

или:

log_event_list_cur->next = 
    log_event_list_cur=(struct log_event_list *) malloc....

С уважением!.

Ответы [ 5 ]

5 голосов
/ 22 августа 2011

Да, первый вариант в порядке (правильный код, который ведет себя аналогично первому коду), но ни один из них не является оптимизацией. Они будут скомпилированы в один и тот же машинный код. Делайте то, что вы считаете наиболее читабельным.

Второй ведет себя по-разному, поскольку log_event_list_cur присваивается новой записи списка до установки next.

1 голос
/ 22 августа 2011

Как уже указывалось, компилятор, вероятно, будет выдавать один и тот же код для всех трех версий.

Вместо , если вы действительно хотите сделать это быстрее, используйте свободный список то есть второй список, который содержит в настоящий момент неиспользуемые элементы списка.Таким образом, «выделение» нового члена означает просто выталкивание элемента из свободного списка (аналогично «освобождение» означает простое нажатие элемента в свободном списке).Таким образом, у вас не будет накладных расходов malloc / free для каждого нового «распределения».Очевидно, что если свободный список пуст и вам нужно выделить нового участника, вам все равно придется звонить malloc, но, надеюсь, это случится редко.

Кстати, надеюсь, вы просто пропустилипроверьте возвращаемое значение malloc.В противном случае, если malloc вернет NULL, скорее всего, вскоре после этого произойдет сбой ...

1 голос
/ 22 августа 2011

Это не будет иметь никакого значения.Простые назначения все равно будут оптимизированы компилятором.

Узнайте, как минимум, как получить «суть» кода сборки и как вывести вывод сборки из вашего исполняемого файла.В Linux использование objdump -S -d даст вам встроенный код с ассемблером.

0 голосов
/ 22 августа 2011

Перестаньте увлекаться оптимизацией, начните увлекаться читабельностью. Преждевременная оптимизация - корень всего зла.

Первый фрагмент кода в порядке.Понятно что происходит.Связанный список получает новую запись после текущей (предположительно, последней), а затем ток перемещается вперед, чтобы стать последним.

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

0 голосов
/ 22 августа 2011

Как уже упоминалось в других ответах, компилятор должен быть в состоянии оптимизировать любые различия, которые вы показываете; Я бы, вероятно, выбрал первое для удобочитаемости, а также для удобочитаемости. Я бы, вероятно, либо установил #define (или const в более поздних версиях C) со значением для вашего вызова sizeof, и typedef для вашего структура, чтобы немного сжать размер.

[править: согласно комментарию к вопросу, актерский состав даже не нужен, удален.]

[править: согласно другому комментарию к вопросу sizeof (log_node) как const больше не имеет никакого смысла вообще; это (вроде) было, когда было c_log_node_size против sizeof(struct log_event_list), но теперь это просто глупо. (есть другие веские причины не делать этого, как отмечено в комментарии, может быть, sizeof_c_log_node может быть в порядке? нет, нет.): D]

typedef struct log_event_list log_node

и тогда оно становится:

log_event_list_cur->next = malloc(sizeof(log_node));
log_event_list_cur = log_event_list_cur->next;

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

Я начал писать некоторый код для этого, но я не оставил его, потому что мне пришло в голову, что вообще не нужно изобретать велосипед, кроме того, что это интересно. Если вы обнаружите, что было бы полезно оптимизировать этот бит кода, есть возможность для настройки ваших выделений: vmalloc . Я не стал бы связываться с этим, если бы вы не смогли действительно продемонстрировать, что это было узким местом. Хотя об этом приятно думать. :)

...