Почему компиляторы так глупы?

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

Итак, хороший ответ:

  1. Если вы хотите только запросить json или другой тип содержимого install Запросить или аналогичный инструмент и изменить заголовок Accept.
  2. Если вы хотите использовать POST и умело отформатировали json, xml и т. д., используйте надлежащий Расширение API-тестирования, например Postman или ARC .

39
задан 2 revs 2 January 2009 в 11:19
поделиться

25 ответов

О, я не знаю. Иногда компиляторы довольно умны. Рассмотрите следующую программу C:

#include <stdio.h>  /* printf() */

int factorial(int n) {
   return n == 0 ? 1 : n * factorial(n - 1);
}

int main() {
   int n = 10;

   printf("factorial(%d) = %d\n", n, factorial(n));

   return 0;
}

На моей версии [1 111] GCC (4.3.2 на [1 112] тестирование Debian), когда скомпилировано без оптимизации, или -O1, это генерирует код для factorial() как, Вы ожидали бы, с помощью рекурсивного вызова для вычисления значения. Но на -O2, это делает что-то интересное: Это компилирует вниз в жесткий цикл:

    factorial:
   .LFB13:
           testl   %edi, %edi
           movl    $1, %eax
           je  .L3
           .p2align 4,,10
           .p2align 3
   .L4:
           imull   %edi, %eax
           subl    $1, %edi
           jne .L4
   .L3:
           rep
           ret

Довольно впечатляющий. Рекурсивный вызов (даже не рекурсивный хвостом) был полностью устранен, таким образом факториал теперь использует O (1) стековое пространство вместо O (N). И хотя у меня есть только очень поверхностное знание x86 блока (на самом деле AMD64 в этом случае, но я не думаю, что любое из расширений AMD64 используется выше), я сомневаюсь, что Вы могли записать лучшую версию вручную. Но что действительно дуло, мой ум был кодом, который он генерировал на -O3. Реализация факториала осталась такой же. Но main() измененный:

    main:
   .LFB14:
           subq    $8, %rsp
   .LCFI0:
           movl    $3628800, %edx
           movl    $10, %esi
           movl    $.LC0, %edi
           xorl    %eax, %eax
           call    printf
           xorl    %eax, %eax
           addq    $8, %rsp
           ret

Посмотрите movl $3628800, %edx строка? gcc предварительно вычисляет factorial(10) во время компиляции. Это даже не звонит factorial(). Невероятный. Моя шляпа прочь группе разработчиков GCC.

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

(Адаптированный от регистрация на моем блоге .)

108
ответ дан 4 revs, 4 users 65% 5 August 2019 в 15:39
поделиться

Это вынуждает Вас (программист) думать о том, что Вы пишете. Вынуждая компиляторы сделать Ваша работа для Вас не помогает никому: это делает компиляторы намного более сложными (и медленнее!), и это делает Вас более глупыми и менее внимательными к Вашему коду.

-2
ответ дан Sophie Alpert 5 August 2019 в 15:39
поделиться

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

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

В Вашем случае компилятор мог бы оптимизировать его, потому что это "думает", что должно быть оптимизировано в другом отношении, но почему остаются там?

Экстремальное значение другая ситуация. У нас есть умный компилятор, компилирующий Windows. Тонны кода для компиляции. Но если это умно, это сводит его к 3 строкам кода...

"starting windows"
"enjoy freecell/solitaire"
"shutting down windows"

Остальная часть кода является устаревшей, потому что это никогда не используется, затрагивается, получается доступ. Мы действительно хотим это?

-1
ответ дан 2 revs, 2 users 76% 5 August 2019 в 15:39
поделиться

Это - пример функционального кода процессуального кодекса v.

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

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

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

0
ответ дан pro 5 August 2019 в 15:39
поделиться

Абсолютная оптимизация является неразрешимой проблемой, которая означает, нет никакой Машины Тьюринга (и, поэтому, никакая компьютерная программа), который может привести к оптимальной версии ЛЮБОЙ данной программы.

Некоторая простая оптимизация может быть (и, на самом деле), сделанный, но, в примерах Вы дали...

  1. , Чтобы обнаружить, что Ваша первая программа всегда печатает нуль, компилятор должен был бы обнаружить, что x остается постоянным несмотря на все повторения цикла. Как может Вы объяснять (я знаю, это не лучшее слово, но я не могу придумать другого), это к компилятору?

  2. , Как компилятор может знать, что StringBuilder является правильным инструментом для задания без КАКОЙ-ЛИБО ссылки на него?

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

1
ответ дан 3 revs 5 August 2019 в 15:39
поделиться

Поскольку разработчики компилятора пробуют, добавляет оптимизация для вещей, которые имеют значение (я надеюсь), и которые измеряются в *сравнительные тесты Stone (я боюсь).

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

то, Что я чувствую себя смущающим, - то, что даже сегодня большинство компиляторов генерирует код для проверки на switchValue быть больше, чем 255 для плотного или почти полного переключателя на неподписанном символе. Это добавляет 2 инструкции к большей части внутреннего цикла интерпретатора байт-кода.

0
ответ дан 2 revs, 2 users 83% 5 August 2019 в 15:39
поделиться

Я никогда не видел точку в устранении мертвого кода во-первых. Почему программист писал его?? Если Вы собираетесь сделать что-то о мертвом коде, объявите его ошибка компилятора! Это почти наверняка означает, что программист сделал ошибку - и для нескольких случаев это не делает, директива компилятора для использования переменной была бы надлежащим ответом. Если я поместил мертвый код в стандартную программу, я хочу выполняемый - я, вероятно, планирую осмотреть результаты в отладчике.

случай, где компилятор мог делать некоторое хорошее, вытаскивает инварианты цикла. Иногда ясность говорит для кодирования вычисления в цикле, и наличие компилятора выходят, такие вещи были бы хороши.

1
ответ дан Loren Pechtel 5 August 2019 в 15:39
поделиться

Это почти полагало, что плохая практика оптимизирует вещи как это при компиляции вниз в байт-код JVM. Sun javac действительно имеет некоторую основную оптимизацию, как делает scalac, groovyc, и т.д. Короче говоря, что-либо, что это является истинно определенным для языка, может быть оптимизирован в рамках компилятора. Однако вещи как это, которые, очевидно, изобретены так, чтобы быть агностиком языка, уменьшатся через просто из политики.

причина этого - он, позволяет HotSpot иметь намного более последовательное представление байт-кода и его шаблонов. Если компиляторы начинают слоняться без дела с пограничными случаями, который уменьшает способность VM оптимизировать общий случай, который не может быть очевидным во время компиляции. Steve Yeggie нравится к арфе на приблизительно этом: оптимизация часто легче , когда выполнено во времени выполнения умной виртуальной машиной. Он даже идет, насколько утверждать, что HotSpot разделяет оптимизацию javac. В то время как я не знаю, верно ли это, это не удивило бы меня.

Для суммирования: компиляторы, предназначающиеся для VMs, имеют совсем другой набор критериев, особенно в области оптимизации и когда это является соответствующим. Не идите, обвиняя разработчики компилятора в отъезде работы к far-more-capable JVM. Как указано несколько раз на этом потоке, современные компиляторы, предназначающиеся для собственной архитектуры (как gcc семья), чрезвычайно умны, производя неприлично быстрый код посредством некоторой очень умной оптимизации.

1
ответ дан Daniel Spiewak 5 August 2019 в 15:39
поделиться

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

причина глупости компиляторов Java является исторической. Во-первых, исходные реализации Java были интерпретатором, базирующимся, и производительность была consisdered неважный. Во-вторых, многие исходные сравнительные тесты Java были проблематичны для оптимизации. Я вспоминаю один сравнительный тест, который походил много на Ваш второй пример. К сожалению, если бы компилятор оптимизировал цикл далеко, сравнительный тест получил бы деление нулевым исключением, когда это пыталось разделить базовое число к прошедшему времени для вычисления его счета производительности. Таким образом, при записи компилятора Java оптимизации, необходимо было очень бояться оптимизировать некоторые вещи, поскольку люди тогда утверждали бы, что компилятор был поврежден.

1
ответ дан Chris Dodd 5 August 2019 в 15:39
поделиться

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

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

6
ответ дан Chad DeShon 5 August 2019 в 15:39
поделиться

Поскольку мы просто не там все же. Вы, возможно, столь же легко спросили, "почему я должен все еще записать программы..., почему я не могу только питаться в документе требований и иметь компьютер, пишут приложение для меня?"

Разработчики компилятора проводят время на небольших вещах, потому что те - типы вещей, которые прикладные программисты склонны пропускать.

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

3
ответ дан 2 revs 5 August 2019 в 15:39
поделиться

Компиляторы в целом очень умны.

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

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

Даже при том, что Ваш пример прост, все еще может быть трудными ситуациями для рассмотрения.

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

, Если Вы хотите более мощное перемещение оптимизаций на язык более со строгим контролем типов как Фортран или haskell, где компиляторам дают намного больше информации для работы с.

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

7
ответ дан Akusete 5 August 2019 в 15:39
поделиться

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

Неизобретенные примеры работают отлично - большинство компиляторов действительно оптимизирует далеко очевидно бесполезный код.

Изобретенный исследует, будет всегда , озадачивают компилятор. Доказательство, если кто-либо был необходим, что любой программист более умен, чем какая-либо программа.

В будущем, Вам будут нужны более изобретенные примеры, чем, Вы отправили здесь.

2
ответ дан S.Lott 5 August 2019 в 15:39
поделиться

На Вашем первом примере это - оптимизация, которая только работает, если значение является нулем. Дополнительное if оператор в компиляторе должен был искать этот редко замеченный пункт, может не просто стоить того (так как это должно будет проверить на это на каждой переменной). Кроме того, что относительно этого:

int x = 1;
int y = 1;
int z = x - y;
for (int i = 0; i < 100 * 1000 * 1000 * 1000; ++i) {
    z += z + z + z + z + z;
}
System.out.println(z);

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

Некоторая оптимизация действительно заботится о втором примере, который Вы отправили, но я думаю, что видел его больше на функциональных языках и не таком большом количестве Java. Большая вещь, которая затрудняет на более новых языках, исправление обезьяны . Теперь += может иметь побочный эффект , который означает, оптимизируем ли мы его, это потенциально неправильно (например, добавляющая функциональность к +=, который распечатывает текущее значение, будет означать различную программу в целом).

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

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

9
ответ дан 3 revs, 2 users 95% 5 August 2019 в 15:39
поделиться

Серьезно? Почему кто-либо когда-либо писал бы реальный код как этот? По моему скромному мнению, код, не компилятор является "глупым" объектом здесь. Я для каждый совершенно рад, что разработчики компилятора не потрудились тратить впустую свое время, пытаясь оптимизировать что-то как этот.

Редактирование/Разъяснение: я знаю, что код в вопросе предназначен как пример, но это просто подтверждает мою точку зрения: или необходимо пробовать, или быть довольно невежественными для записи в высшей степени неэффективного кода как этот. Это не задание компилятора для содержания нашей руки, таким образом, мы не пишем ужасный код. Именно наша ответственность в качестве людей пишет код для знания достаточно о наших инструментах для записи эффективно и ясно.

14
ответ дан 2 revs 5 August 2019 в 15:39
поделиться

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

Это покрыто в HotSpot FAQ под вопросом, "Я пишу простой цикл во время простая операция, и это медленно. Что я делаю неправильно?".

16
ответ дан 2 revs 5 August 2019 в 15:39
поделиться

Разговор с точки зрения C/C++:

Ваш первый пример будет оптимизирован большинством компиляторов. Если компилятор Java от Sun действительно выполняет этот цикл, это - отказ компиляторов, но честное слово что любое сообщение 1990 C, C++ или компилятор Фортрана полностью устраняет такой цикл.

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

Полный я удовлетворен компиляторами оптимизации, может сделать в эти дни.

46
ответ дан 2 revs, 2 users 94% 5 August 2019 в 15:39
поделиться

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

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

  • Небольшие изменения в коде не должны приводить к резким различиям в производительности.

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

Все эти критерии препятствуют "волшебной" оптимизации, которая применяется только к угловым случаям.

<час>

Обоим из Ваших примеров обновили переменная в цикле, но не используемые в другом месте . Этот случай на самом деле довольно трудно взять, если Вы не используете своего рода платформу, которая может объединить устранение невыполняемого кода с другой оптимизацией как распространение копии или постоянное распространение. К простой оптимизатор потока данных переменная не выглядит мертвой. Для понимания, почему эта проблема трудна посмотрите статья Lerner, Рощи и Камер в 2002 POPL , который использует этот самый пример и объясняет, почему это твердо.

23
ответ дан 2 revs 5 August 2019 в 15:39
поделиться

По-моему, я не полагаю, что это - задание компилятора для фиксации то, что, честно, плохо кодирует. Вы, вполне явно, сказали компилятору о желании того первого выполняемого цикла. Это совпадает с:

x = 0
sleep 6 // Let's assume this is defined somewhere.
print x

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

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

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

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

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

Однако позвольте мне оставить Вас со старой историей компилятора ФОРТРАНА VAX, который подвергался сравнительному тесту для производительности, и было найдено, что это было многие порядки величины быстрее, чем его самый близкий конкурент.

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

112
ответ дан 7 revs, 2 users 98% 5 August 2019 в 15:39
поделиться

Поскольку другие обратились к первой части Вашего вопроса соответственно, я попытаюсь заняться второй частью, т.е. "автоматически использует StringBuilder вместо этого".

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

112-секундный, поскольку библиотеки развиваются (особенно в Java) намного быстрее, чем языки, не отставая от них и зная то, что удерживает от использования то, какой и что другой компонент библиотеки мог бы лучше подходить для задачи, будет гераклова задача. Также, вероятно, невозможный, поскольку этот предложенный оптимизатор должен был бы точно понять и Ваше намерение и намерение каждого доступного компонента библиотеки, и так или иначе найти отображение между ними.

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

2
ответ дан Drew Hall 5 August 2019 в 15:39
поделиться

Компиляторы так умны, как мы делаем их. Я не знаю слишком много программистов, которые потрудились бы писать компилятор, который проверит на конструкции, такие как те, Вы использовали. Большая часть концентрата на более типичных способах улучшить производительность.

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

-1
ответ дан Jim C 5 August 2019 в 15:39
поделиться

На самом деле Java должен использовать строкового разработчика в Вашем втором примере.

основная проблема с попыткой оптимизировать эти примеры далеко состоит в том, что выполнение так потребовало бы доказательство теорем . То, что означает, что компилятор должен был бы создать математическое доказательство того, что Вы - код, на самом деле сделает. И это не маленькая задача вообще. На самом деле способность доказать, что весь код действительно имеет эффект, эквивалентна проблеме остановки.

Несомненно, можно придумать тривиальные примеры, но количество тривиальных примеров неограниченно. Вы могли всегда думать о чем-то еще, таким образом, нет никакого способа поймать их всех.

, Конечно, возможно для [приблизительно 111] код, как доказывать, не иметь любой эффект, как в Ваших примерах. То, что Вы хотели бы сделать, имеют компилятор, оптимизируют далеко каждую проблему, которая может быть доказана неиспользованной во время P.

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

Вы могли бы хотеть изучить Haskel, который я думаю, имеет самую усовершенствованную теорию, доказывающую материал, хотя я не уверен в этом. Я не знаю это сам.

1
ответ дан Chad Okere 5 August 2019 в 15:39
поделиться

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

1
ответ дан Rauhotz 5 August 2019 в 15:39
поделиться

Ну, я могу только говорить о C++, потому что я - новичок Java полностью. В C++ компиляторы являются бесплатными игнорировать любые требования языка, помещенные Стандартом, пока заметный , поведение , как будто компилятор на самом деле эмулировал все правила, которые помещаются Стандартом. Заметное поведение определяется как [1 121] любые чтения и записи к энергозависимым данным и вызовы к библиотечным функциям . Рассмотрите это:

extern int x; // defined elsewhere
for (int i = 0; i < 100 * 1000 * 1000 * 1000; ++i) {
    x += x + x + x + x + x;
}
return x;

компилятору C++ позволяют оптимизировать, что часть кода и просто добавляет собственное значение к x, который следовал бы из того цикла однажды, потому что код ведет себя , как будто цикла никогда не происходило, и никакие энергозависимые данные, ни библиотечные функции включены, который мог вызвать необходимые побочные эффекты. Теперь рассмотрите энергозависимые переменные:

extern volatile int x; // defined elsewhere
for (int i = 0; i < 100 * 1000 * 1000 * 1000; ++i) {
    x += x + x + x + x + x;
}
return x;

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

<час>

Разговор о Java, я протестировал Ваш цикл, и это происходит, который Компилятор Java GNU (gcj) берет в беспорядочном количестве времени для окончания цикла (это просто не закончилось, и я уничтожил его). Я включил флаги оптимизации (-O2), и это произошло, это распечатало 0 сразу:

[js@HOST2 java]$ gcj --main=Optimize -O2 Optimize.java
[js@HOST2 java]$ ./a.out
0
[js@HOST2 java]$

, Возможно, что наблюдение могло быть полезным в этом потоке? Почему это, оказывается, так быстро для gcj? Ну, одна причина, конечно, состоит в том, что gcj компилирует в машинный код, и таким образом, это не имеет никакой возможности оптимизировать тот код на основе поведения во время выполнения кода. Это берет всю свою крепкость вместе и пытается оптимизировать столько, сколько это может во время компиляции. Виртуальная машина, однако, может скомпилировать код Как раз вовремя как этот вывод шоу Java этого кода:

class Optimize {
    private static int doIt() {
        int x = 0;
        for (int i = 0; i < 100 * 1000 * 1000 * 1000; ++i) {
            x += x + x + x + x + x;
        }
        return x;
    }
    public static void main(String[] args) {
        for(int i=0;i<5;i++) {
            doIt();
        }
    }
}

Вывод для java -XX:+PrintCompilation Optimize:

1       java.lang.String::hashCode (60 bytes)
1%      Optimize::doIt @ 4 (30 bytes)
2       Optimize::doIt (30 bytes)

, Как мы видим, это, JIT компилирует функцию мелкой монеты 2 раза. На основе наблюдения за первым выполнением это компилирует его во второй раз. Но это, оказывается, имеет тот же размер как байт-код два раза, предполагая, что цикл все еще на месте.

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

12
ответ дан 4 revs, 2 users 97% 5 August 2019 в 15:39
поделиться

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

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

Я тоже предпочел бы иметь malloc (100000), чем тысячу malloc (100) при выполнении s + = "s"; но сейчас эта вещь выходит за рамки компиляторов и должна быть оптимизирована людьми. Это то, что язык D пытается решить, вводя чистые функции .

Как упоминалось здесь в других ответах,

1
ответ дан 27 November 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: