![]() |
многократный вызов функции. оптимизация
Вопрос чисто ради интереса.
Код:
for (int i = 0; i < someshit.count(); i++) {}Код:
int arraySize = someshit.count();Интересует мнение людей, которые знают как это работает на более низком уровне. Много ли различных вызовов\обращений к памяти экономит второй пример и есть ли вообще смысл оптимизировать код данным образом? |
Цитата:
|
второй вариант значительно будет виден когда someshit.count() будет около 1кк или больше...
смотря конечно что такое someshit если это класс а count() функция, то надо смотреть как она получает результат... тут может быть несколько споссобов 1)ф-ия в цикле считает результат и выдает... 2)в классе предусмотрена переменная для хранения этого результата, которая при каждом изменеии данных пересчитывается и сохраняется в памяти тогда count() просто считывает эту переменную и выдает её результат. сам понимаеш если первый вариант то это очень много лишних операций для тебя... если же в классе все как во втором случае то ты всеравно на каждый шаг цикла получаеш 1-2 лишних операции... p.s. если ты уверен что значение count() у тебя всегда будет не больше 1000 то оба споссоба для человека будут одинаковы (человек не сможет заметить разницу выполнения программ в 100-200 тактов (ну может и побольше)) |
Однозначно второй вариант
|
второй вариант, только пишу так:
Код:
for (int i = 0, arraySize = someshit.count(); i < arraySize; i++) {} |
Конечно второй вариант быстрее.
З.Ы. А если ещё и цикл разложить в последовательные вызовы и таким образом избавиться от условия на каждой итерации, так вообще :) Но это не твой случай, т.к. ты не знаешь count. Единственное - умные компиляторы всё это дело оптимизируют. З.З.Ы. А по поводу названия опроса "Как вы пишете", я пишу как во 2м варианте, но к примеру Фаулер, в книге по рефакторингу рекомендует писать как в первом варианте, для того чтобы избавится от лишних переменных и сделать код более наглядным. Ну это правда к этапу оптимизации не относится, а делается раньше :) |
Цитата:
а наглядность это не для кода... (но если кодер ставит на первый план наглядность то это его дело) |
KIR@PRO, код пишут для людей а не для компов. (Ну без фанатизма, я к тому что код должен быть понятен) В больших проектах за непонятный код надо по пальцам стучать. Представь как его потом апдейтить и багфиксить. Но по мне временные переменные - наоборот могут внести ясность, за счёт нормального имени переменной.
З.Ы. А оптимизация это уже последний этап, когда код работает и ты по нему бегаешь профайлером, выясняя что именно стоит оптимизировать. |
дак я и говорю что элементарную табуляцию и прочее надо соблюдать, названия переменных делать понятными... это уде слишком, этож прямое принебрежение производительностью ради маленькой наглядности...
p.s. может мы просто не поняли друг друга))) я же говорил именно о том что надо избавляться от временных переменных чтоб сделать код более наглядным... p.p.s. но это мнение каждого из нас) |
по-моему такого вообще не должно быть, должна быть переменная Size, которая обновляется сама собой.
проголосовал за первое, случайно. |
посмотрел...
результат под запуском профайлера:
http://img21.imageshack.us/img21/396...2009222211.jpg результат профайлера: http://img18.imageshack.us/img18/726...2009222305.jpg используемый код: PHP код:
p.s. было интересно, а будет-ли разница? Оказалось есть. Проц Core2Duo E8400 |
Цитата:
В твоем примере разница между вызовом свойства и локальной переменной - минимальна. А вот если count() - это метод, со сложной внутренней реализацией, то разница будет намного большей. PS Да, и использованный тест не очень показателен. Нужно что бы время выполнения было хотя бы несколько секунд. Разница в 3 сотых - вполне может быть случайной. Особенно в дотнете. |
Цитата:
Довольно часто можно встретить такое: Код:
class a |
Цитата:
З.Ы. Если не понятно почему, то во первых чтобы со стороны никто не мог внезапно изменить данное поле (в случае public ты можешь записать левое значение в переменную size и класс об этом не узнает, чем черевато - понятно), а так ты можешь сделать поле доступным извне только на чтение, или только на запись, во вторых если требуется изменить внутреннюю структуру класса и удалить/переименовать эту переменную, чтобы не требовалось искать всех пользователей класса, и менять их. (Просто достаточно будет изменить реализацию геттеров/сеттеров, тогда интерфейс класса останется неизменным). Вот по крайней мере 2 плюса использования геттеров сеттеров. Ну ещё можно при помощи изменения геттеров подгонять объекты под требования пользователя класса, или добавлять в них проверки ввода, но сложная логика в геттерах/сеттерах - не клёво и неправильно. |
Проголосовал за 1-й вариант, потом вдумался и пришёл к выводу что пишу всё-же по второму варианту.
В принципе если метод count() имеет какую то сложную реализацию то это существенно скажется на производительность. |
Цитата:
|
Цитата:
вечером как окажусь дома переделаю... думаю будет нагляднее. update: не выдержал, проверил с LINQ на работе, результат без профайлера: Method 1. Time elapsed: 00:00:00.0468753 Method 2. Time elapsed: 00:00:00 update2: с профайлером: Method 1. Time elapsed: 00:00:00.0781250 Method 2. Time elapsed: 00:00:00.0156250 |
сколько раз гонялся тест? нужно минимум для каждого варианта прогнать по 10-50 раз. чтобы исключить момент подгрузки кода в кеш.
по поводу опроса - не хватает еще варианта ответа - одно***ственно. ибо потери на вызове метода, пусть даже виртуального, не окажут никакого ощутимого влияния. а лишняя локальная переменная в таком месте, объявленная вне цикла, может позже помешать вынести этот цикл в отдельный метод. так что чисто из соображений дальнейшей поддержки проекта и читабельности я бы предпочел первый вариант. по поводу форматирования - почитайте Макконнелла. по поводу переменных - int x = strlen("blabla") - strlen("bla"); на уровне асма будет эквивалентен коду int blabla_len = strlen("blabla"); int bla_len = strlen("bla"); int blabla_len_dif = blabla_len - bla_len; суть отказа от локальных переменных как раз в другом. чтобы в больших методах можно было легко читать логику. этот код например в случае нахождения в большом методе выносится в отдельный и заменяется на blabla_len_dif("blabla", "bla"); ибо это понятнее и требует меньше времени на чтения, ибо банально занимает 1 строку. ну и в добавок сей код можно в дальнейшем вызывать из любого места класса, плюс сделать метод публичным и дать другим классам с ним работать. зы: чтите Фаулера, Макконнелла, GoF. |
Совет: пишите так, как проще и меньше кода.
Оптимиировать надо не все подряд, а только узкие места. Все подряд оптимизируют лишь распиздяи ;) |
W!z@rD
попробуй поменять местами тесты Цитата:
|
оптимизировать нада лишь после окончания программирования, после тестов с профайлером. раньше смысла нет. ну и плюс статистика - большая часть выполнения порграммы фокусируется в 10% строках кода. так что если будете оптимизировать весь код - потратите 90% времени впустую.
|
Цитата:
|
не для больших объемов данных, а для сбора той же самой статистики.
|
ну пох =) просто имхо для данного случая результат будет принципиально разнИца при первом тесте, в остальных будет уже среднее значение. ну кароч кто как хочет, тот так и тестит
|
Цитата:
|
Цитата:
Обычный процесс разработки: программирование как удобно, написание тестов и их прогон, рефакторинг, прогон тестов. И так до полного удовлетворения. Затем работа с профайлером, выяснение узких мест и их оптимизация. И вот после этого код уже вполне может стать не таким красивым и элегантным. (До этого код прост и понятен, в результате рефакторинга, главное рефакторить почаще) З.Ы. В общем, присоединюсь к Ra$cal, читайте Фаулера. З.З.Ы. Ну вообще тесты рекомендуют писать до написания кода, но у меня на практике так ни разу не получалось. |
Кстати да. Забыл сказать, что я за первый вариант для веба.
Больше пары десятков итераций на практике не встречается. |
Цитата:
Тестирование может выявить слабые места программы, которые затем нужно оптимизировать более тщательно. Но это не означает что остальной код должен быть грязным. Цитата:
PS И кстати на возможное снижение производительности при замене переменной на вызов метода - пишет сам же Фаулер в той же книжке. |
Algol, дык рефакторинг для того и придуман, чтобы избавляться от грязного кода. А оптимизация (не считая алгоритмической), часто бывает избыточной, и отнимает слишком много времени, для этого и не следует оптимизировать пока не пробежишься по коду профайлером. Это делается после получения работоспособной версии. А задача тестов, не в том чтобы выявлять слабые места программы, а в том, чтобы гарантировать неизменность её работоспособности при последующих изменениях, в том числе при рефакторинге и оптимизации. (Ну или, если полностью следовать TDD, ещё показывает процент готовности приложения)
Цитата:
|
Цитата:
|
Цитата:
Хотя, это зависит от предметной области. Не думаю что в графических движках, например, оптимизация бывает "избыточной" :) |
Цитата:
|
Цитата:
Посмотри внимательно изначальный код. Там метод, а не геттер. |
Algol, лучше написать 10 программ со 100% производительности, чем это же время потратить на 1 с 150%процентной.
Ведь за деньги с 9 остальных программ можно купить железо на увеличение произвродительности на все 10000%. |
Цитата:
но естественно есть варианты кода, где такое не канает, и понадобится другая оптимизация. ну или в случае, когда нет доступа к исходному коду. но тогда как вариант можно просто наследовать класс от этого или сделать фасад и добавить сию фишку руками. |
бла-бла-бла
|
Цитата:
Дело в приоритетах. Я выбираю сдать проект. |
Цитата:
Просто лично я (написать триста раз ИМХО?) привык писать код максимальный по быстродействию. Если я вижу что вариант с временной переменной быстрее (а для меня еще и читабельнее, интуитивно понятнее!) чем с многократным вызовом функции - то мне что, специально писать заведомо более медленный вариант? Только потому что так сказал Фаулер, и что это по фен-шую? Я автоматом выношу все вызовы функций из цикла, если они не зависят от параметра, и для меня это совершенно не составляет труда и времени, а потому ни о каком завале проекта речь не идет. Конечно, если оптимизация с сомнительной рациональностью занимает пол дня, я ее, разумеется, не делаю. Но если она у меня на автомате, зачем от нее отказываться? |
я бы еще добавил - выбираю сдать проект, суметь потом этот проект поддерживать, исправлять и дополнять
[added] если ты пишешь проект один - то никакой проблемы нету. но когда пишешь в команде - тут главным становится критерий читабельности, а не скорости. поэтому все и пишут читабельный код. потом профайлят, и узкие места приводят к менее читабельному виду. но таких мест не много и все счастливы - и клиент получил быструю программу, и разработчики могут с ней работать дальше. а вариант на ходу оптимазить все операции - нерационален. я раньше так же писал. долго писал =) потом понял что лажа это все. не стоит оно усилий потраченых. но это все дело вкуса. на фаулера никто не молится. просто находим с ним общие решения =) |
Цитата:
|
| Время: 13:36 |