Как избежать «Плохой интуиции разработчика»?


22

Я видел в статье, которая выдвинула это утверждение:

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

Как разработчик может избежать этой плохой интуиции? Существуют ли хорошие инструменты для поиска того, какие части вашего кода действительно нуждаются в оптимизации (для Java)? Знаете ли вы какие-нибудь статьи, советы или хорошие чтения по этой теме?


1
Это сводится к тому, «как мне избежать [полагаться] на интуицию [при принятии решений]?» Просто: вы проверяете с помощью достоверных фактов и данных. Таким образом, в случае оптимизации, с точки зрения разработчика: вы ориентируетесь.
Хайлем

Ответы:


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

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

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


51
Или, проще говоря: «Чтобы избежать плохой интуиции оптимизации, не используйте интуицию. Измеряйте».
Kyralessa

6
Вот почему ваш ответ, а мой просто комментарий. : P
Kyralessa

2
@ Томас, если вы играете с удобочитаемостью и удобством сопровождения, вы не обращаете внимания на проблемы с производительностью, не так ли?

3
@ Томас, я не согласен. Даже в рамках спецификации вам необходимо тщательно протестировать новый код. Это не нужно для старого кода. Revert.

2
@ Thorbjørn После настройки производительности вам также необходимо тщательно протестировать новый код. Экономия времени или памяти не имеет смысла, если вы ввели дефект.
Томас Оуэнс

10

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

Java делает это довольно легко с помощью инструмента VisualVM , который был включен в последние выпуски Java Development Kit (JDK). Идея состоит в том, чтобы выяснить, какие методы вызываются чаще всего и в каких методах вы проводите большую часть своего времени, как в коде, так и во внешних библиотеках. Вы также можете получить данные о производительности сборки мусора, чтобы настроить сборщик и настроить минимальное / максимальное пространство кучи, необходимое для вашего приложения.


VisualVM не находится в JRE, только в JDK.

1
@ Thorbjørn Ravn Andersen Хороший звонок. Я должен уточнить. Однако, если вы занимаетесь разработкой на Java, у вас обычно установлен JDK (хотя вы, возможно, используете OpenJDK или аналогичный - я не знаю, поставляются ли они с VisualVM).
Томас Оуэнс

1
Я очень часто переключаю рабочие пространства в Eclipse, который по умолчанию использует JRE, который запустил Eclipse. Поскольку установить JRE гораздо проще, чем JDK, мы постепенно перешли на процесс сборки ant, который включает в себя компилятор Eclipse и, следовательно, может работать на простой JRE. Следовательно, в наши дни вы действительно можете выполнять реальную работу без JDK. VisualVM может быть загружен отдельно, что упрощает его использование с данной версией Java, поскольку в Windows 64-битная JVM не может подключаться к 32-битной JVM и наоборот.

9

Поскольку здесь все говорят о профилировщиках, я сосредоточусь на этой части вопроса.

Как разработчик может избежать этой плохой интуиции?

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

Вы обнаружите, что делаете это, и обнаружите, что не должны этого делать.
А потом опять.
И снова.

Ранняя оптимизация - один из главных грехов программистов .

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


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

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

это звучит для меня как принцип ЯГНИ - Это НЕ ТЫ!
Е.Л. Юсубов

7

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

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


5

Посмотрите также, сколько памяти использует ваша программа, а не только ее скорость или время выполнения.

Многие программисты, работающие с такими языками сборки мусора, как Java, ошибочно полагают, что сборка мусора предотвращает утечки памяти. Это не относится к делу. Если вы удерживаете ссылку на объект, который вам больше не нужен, он не будет собран, и поэтому он будет течь.

Я видел веб-приложения на Java, которые были настолько протекающими, что на их сервере не хватало места подкачки!

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


1

мое лекарство - начать с получения четких ответов на два вопроса:

  1. как измерить производительность (например, измерить время загрузки данных )
  2. каково целевое значение (например, загрузка данных за 3 секунды или менее с достоверностью 95% )

Изученный выше трюк от парней из команды тигров , которых когда-то пригласили спасти сломанную версию нашего продукта. Этот релиз был сломан по соображениям производительности, он мог сделать компанию потерять стратегического клиента, что оправдывало участие тигров (довольно дорого). Я был назначен, чтобы помочь им в разъяснении деталей проекта; также использовал это как возможность узнать немного или два о производительности.


1

То, что я нашел, является лучшим противоядием от преждевременной оптимизации, это метод .

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

Реальная оптимизация - это преждевременная оптимизация, так как охота накормить семью - отстрел консервных банок. Это все о поиске карьера.


1
И, к сожалению, вы можете нести только 200 фунтов обратно в вашу семью, так что не стреляйте белками весь день.
Джордан

1

Старый вопрос, но я предложу этот ответ, который значительно отличается от других.

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

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


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

0

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

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

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

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

Человеческая интуиция за пределами очевидной алгоритмической сложности часто начинается неправильно, потому что то, что эффективно для машины, и то, что эффективно для человеческого разума, сильно отличается. Поначалу не так уж и интуитивно думать об иерархиях памяти, переходящих от регистров к кэшу ЦП к DRAM на диск. Интуитивно понятно, что избыточная арифметика может быть быстрее, чем больше разветвлений или обращений к памяти в справочной таблице, чтобы пропустить некоторую обработку. Мы склонны думать с точки зрения того, сколько работы нужно проделать, и при этом не учитывать такие вещи, как стоимость принятия решений, загрузка и хранение памяти. То, что эффективно для аппаратного обеспечения, часто очень нелогично, так как вначале нарушит все ваши человеческие предположения,

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


0

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

На моем личном опыте я был свидетелем того, как особенно блестящий разработчик (но с пробелами в том, как пользователи на самом деле используют программное обеспечение) оптимизировал алгоритм подразделения с помощью профилировщика (очень хороший, дорогой и всеобъемлющий: VTune от Intel с графом вызовов). выборка поверх профилировщиков графических процессоров) для сеток позволяет добиться удивительных результатов при использовании миллиардов граней в графическом процессоре при разделении простых примитивов, таких как кубы, с 6 клеточными / входными полигонами. За исключением того, что он настроил и настроил его на тот тестовый пример, который был непохож на любой реальный пример использования (пользователи не хотят, чтобы миллиард граней к подразделенному кубу начинал напоминать идеальную сферу, их входные данные подразделения, как правило, похожи на символы и транспортные средства и другие сложные входы).

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.