Разгрузка конструктора

50 views
Skip to first unread message

Alex Davydov

unread,
Mar 5, 2010, 12:32:45 PM3/5/10
to ruf...@googlegroups.com
Существует общая рекомендация разгружать конструктор. Т.е., ставить там сохранение аргументов (если приходят) и вызов процедуры инициализации. И больше ничего туда не пихать. А вот почему?

Yuri Zhloba

unread,
Mar 5, 2010, 12:36:31 PM3/5/10
to ruf...@googlegroups.com
Код в конструкторе интерпретируется, и поэтому выполняется медленнее. Код обычных методов компилируется, и выполняется быстрее :)

Jivel

unread,
Mar 5, 2010, 12:54:38 PM3/5/10
to ruFlash
> Код в конструкторе интерпретируется

Можно какой нибудь линк на эту тему?

Valentin Simonov

unread,
Mar 5, 2010, 12:58:35 PM3/5/10
to ruf...@googlegroups.com
что это вообще значит?


Alex Davydov

unread,
Mar 5, 2010, 1:06:10 PM3/5/10
to ruf...@googlegroups.com
Сам сижу думаю...

Ivan Dembicki

unread,
Mar 5, 2010, 1:03:53 PM3/5/10
to ruf...@googlegroups.com
Hello Alex,

> Существует общая рекомендация разгружать конструктор. Т.е., ставить там
> сохранение аргументов (если приходят) и вызов процедуры инициализации. И
> больше ничего туда не пихать. А вот почему?

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

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

Никакие другие мотивы мне неизвестны.

--
iv
http://www.bezier.ru
http://bezier.googlecode.com

Alex Davydov

unread,
Mar 5, 2010, 1:10:16 PM3/5/10
to ruf...@googlegroups.com
2Ivan Dembicki:

О©╫! О©╫О©╫О©╫О©╫О©╫О©╫О©╫!
О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫ - О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫!

Dima Pilipenko

unread,
Mar 5, 2010, 1:11:42 PM3/5/10
to ruf...@googlegroups.com
А переопределять конструктор наследуемого класса это разве хорошая организация кода?

Ivan Dembicki

unread,
Mar 5, 2010, 1:36:23 PM3/5/10
to ruf...@googlegroups.com
Hello Dima,

> А переопределять конструктор наследуемого класса это разве хорошая
> организация кода?

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

Yuri Zhloba

unread,
Mar 5, 2010, 1:39:03 PM3/5/10
to ruf...@googlegroups.com
Заставили меня, ленивого, гуглить пруфлинки :) Ну ладно, нагуглил.

Code inside the constructor is not optimized by the Just-in-time compiler (JIT).
To use JIT optimized code there is the possibility to call a function out of the
constructor. The code inside that function is then optimized again.

ActionScript 3 optimization techniques http://je2050.joa-ebert.com/files/misc/as3opt.pdf

Oleksandr Izvekov

unread,
Mar 5, 2010, 1:55:14 PM3/5/10
to ruf...@googlegroups.com
просто не стоит путать конструктор класса и инициализацию экземпляра,
первое переопределять плохо, так как можно напортачить в структуре, второе необходимо для гибкости

alexander nemtsov

unread,
Mar 5, 2010, 2:00:44 PM3/5/10
to ruf...@googlegroups.com

Потому что performance.

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

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

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

Elastic racetrack - вот вам ключевые слова для дальнейших раскопок в
гугле.

> Существует общая рекомендация разгружать конструктор. Т.е., ставить
> там сохранение аргументов (если приходят) и вызов процедуры
> инициализации. И больше ничего туда не пихать. А вот почему?
>

Александр Немцов
alexande...@gmail.com



Ivan Dembicki

unread,
Mar 5, 2010, 2:01:44 PM3/5/10
to ruf...@googlegroups.com
Hello Yuri,

> Code inside the constructor is not optimized by the Just-in-time compiler (JIT).

- круто, спасибо, не знал.

Valentin Simonov

unread,
Mar 5, 2010, 4:07:06 PM3/5/10
to ruf...@googlegroups.com
интересно почему
вот тут на 8ой минуте тоже говорят
http://tv.adobe.com/watch/360flex-conference/diving-deep-with-the-flex-compo
nent-lifecycle

makc

unread,
Mar 5, 2010, 4:28:18 PM3/5/10
to ruFlash
> Причина проста: код в конструкторе выполняется обязательно и в
> подклассе его никак не переопределить.

http://juick.com/blooddy/560275

Flop Serg

unread,
Mar 5, 2010, 5:26:23 PM3/5/10
to ruf...@googlegroups.com



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

Ну не правда ) вот например чит

public class Foo extends Bar {
public function Foo() {
if (false) {
super() // суперконструктор не вызовется
}
}
}


makc

unread,
Mar 5, 2010, 6:36:09 PM3/5/10
to ruFlash
> if (false) {

читай линку выше http://juick.com/blooddy/560275

Dima Pilipenko

unread,
Mar 6, 2010, 4:28:56 AM3/6/10
to ruf...@googlegroups.com
И что?
то вот фолс по сути истинное внутри скобок..

Denis Kolyako

unread,
Mar 6, 2010, 4:39:42 AM3/6/10
to ruf...@googlegroups.com

> то вот фолс по сути истинное внутри скобок..


Нет, оно вообще не вкомпиливается.

Денис Коляко
______________________________________________________________________
e...@timezero.ru | http://etcs.ru/ | http://timezero.com/


Dima Pilipenko

unread,
Mar 6, 2010, 4:51:38 AM3/6/10
to ruf...@googlegroups.com
хорошо, ну а смысл ему вкомпиливаться, если он пропускает в свои обьятия выполнения кода?

Ivan Dembicki

unread,
Mar 6, 2010, 9:06:44 PM3/6/10
to ruf...@googlegroups.com
Hello,

хак - штука небезопасная.
Хаки полезно знать как особенности реализации данной версии языка или
компилятора.
Но если завтра компилятор неожиданно станет умнее настолько, что
поймёт что !true равно false, то кое-кого у нас порой ждет какое-то
количество бессонных ночей в поисках неизвестно откуда взявшейся
кое-какой ошибки.

Пользуясь случаем передаю привет создателям фильма "Следствие ведут знатоки".

Daniil Tutubalin

unread,
Mar 7, 2010, 4:19:26 AM3/7/10
to ruf...@googlegroups.com
Причём, опасно не только развитие адобовского компилятора.
Какая-нибудь сторонняя фирма Eboda (не бойтесь, прочитайте наоборот)
выпустит свой компилятор, который и сам будет работать в 10 раз
быстрее адобовского, и код будет генерировать более оптимальный, при
этом с полным сохранением совместимости. Соответственно, компилятор
станет популярным у разработчиков. У всех, кроме тех, кто наоставлял в
проектах такие хаки.
И его будет ничем не обмануть ни if (!true), ни if (Math.sin(x) == 4)
/* военное время */
Помимо этого существуют различные оптимизаторы SWF, которые тоже могут
не так понять некоторые хаки.

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

public class MyBaseControl extends Sprite {
public var textField:TextField;

public function MyBaseControl() {
textField = new TextField();
addChild(textField);
}
}

Затем понадобилось сделать класс MySpecificControl, который наследует
от MyBaseControl, но в котором вместо TextField должен использоваться
MegaCoolTextField - наследник TextField с дополнительным функционалом.
Это получается, что теперь в конструкторе MySpecificControl надо
сперва убить старый textField, затем создать и добавить новый.

Таким образом небольшой перевес в конструкторе класса может привести к
куда более серьёзному утяжелению конструкторов потомков.

Омар Валиев

unread,
Mar 7, 2010, 4:56:57 AM3/7/10
to ruf...@googlegroups.com
Неудачный пример, имея гетер и сетер утяжеляются они (проверкой на
пришедший TextField и заменой его), а не конструктор.
Подобная ситуация с методами в своих namespace их не переопределить и
обычно такой метод вызывает чтото вроде funcImpl(). А вот в отношении
практики ООП кажется все таки правильно вызывать все конструкторы
подряд до выполнения кода текущего, поэтому есть смысл
инициализировать по требованию, например
public function get someArray():Array{
if(!_someArray) _someArray = new Array();
return _someArray;

Daniil Tutubalin

unread,
Mar 7, 2010, 6:52:29 AM3/7/10
to ruf...@googlegroups.com
> Неудачный пример, имея гетер и сетер утяжеляются они (проверкой на пришедший
> TextField и заменой его), а не конструктор.

А не изврат ли?

Омар Валиев

unread,
Mar 7, 2010, 8:03:25 AM3/7/10
to ruf...@googlegroups.com
Я считаю извратом наследоваться от класса имеющего public свойство,
причем мне не ясно каким будет наследник, а вернее свойство
MegaCoolTextField и как организован к нему доступ (если присваивать к
TextField то как будут обращаться остальные к cool functions этого
MegaCoolTextField). Мне любопытно какие тут есть решения.
> А не изврат ли?

Daniil Tutubalin

unread,
Mar 7, 2010, 9:00:23 AM3/7/10
to ruf...@googlegroups.com
> мне не ясно каким будет наследник, а вернее свойство MegaCoolTextField и как
> организован к нему доступ

Допустим, этот MegaCoolTextField не содержит новых публичных методов и
свойств, но зато умеет вводить кириллицу в любой ОС, закрашивает буквы
градиентом и сразу поддерживает i18n.
То есть с точки зрения API ничем не отличается от TextField, но при
этом разительно отличается поведением и внешним видом.

Омар Валиев

unread,
Mar 7, 2010, 9:14:01 AM3/7/10
to ruf...@googlegroups.com
А кроме вырожденых случаев? Думаю причина рекомендации именно
perfomance а не код интерпретируется или компилируется.

Ivan Dembicki

unread,
Mar 7, 2010, 9:21:17 AM3/7/10
to ruf...@googlegroups.com
Hello Омар,

> Думаю причина рекомендации именно perfomance а
> не код интерпретируется или компилируется.

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

Daniil Tutubalin

unread,
Mar 7, 2010, 9:24:58 AM3/7/10
to ruf...@googlegroups.com
> А кроме вырожденых случаев?

На этот случай есть оператор as.

Омар Валиев

unread,
Mar 7, 2010, 9:35:14 AM3/7/10
to ruf...@googlegroups.com
Если не брать во внимание flex, то почему не использовать init,
initWith... initFrom... после вызова конструктора (или static), это
ведь не расходится с идеей инкапсуляции и запихивание этих метов в
конструктор лишь лишает гибкости (так вроде не только apple в cocoa
делает)

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


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

Alex Davydov

unread,
Mar 7, 2010, 6:18:57 PM3/7/10
to ruf...@googlegroups.com
2 Иван Дембицкий:
> производительность - самое последнее чем стоит озаботиться в
процессе написания программы.
 
Я всёшки надеюсь, что Реалакси не окажется аццким тормозом. :)

Ivan Dembicki

unread,
Mar 8, 2010, 8:38:28 AM3/8/10
to ruf...@googlegroups.com
Hello Alex,

> Я всёшки надеюсь, что Реалакси не окажется аццким тормозом. :)

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

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

Приведу пример:
как-то году в 2002-м я взял чьё-то готовое древовидное меню и вполне
успешно его пользовал в проекте до тех пор, пока меню не стало большим
- больше 500 элементов. Тут оно стало жутко тормозить при
открытии/закрытии веток. Полез изучать код и обнаружил, что при
открытии папки код пробегался дальше по всем элементам дерева
пересчитывая их позицию и... вызывая аналогичный метод в каждом из
них.
В итоге - лавинообразное увеличение - порядка 100 тысяч(!!!) абсолютно
ненужных вызовов.
При этом, в коде автор явно пытался бороться с проблемами
производительности - большинство известных на том момент
микрооптимизаций в коде были были применены. Но не помогли.

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

Ivan Dembicki

unread,
Mar 8, 2010, 9:08:28 AM3/8/10
to ruf...@googlegroups.com
Hello,

ну вот заглянте сюда:
http://je2050.joa-ebert.com/files/misc/as3opt.pdf
выигрыш в самом крутом случае составляет 30 секунд на миллион итераций. Много?
При ста итерациях около трех миллисекунд, т.е. выигрыш от оптимизации
составит три сотых миллисекунды на операцию.
Т.е. в нормальном коде без циклов или при пробежке по небольшому
списку смысл оптимизации отсутствует напрочь.
И это заметьте - в самом крутом примере. Остальные примеры дают
считаные десятки миллисекунд выигрыша на миллион итераций. Т.е. вообще
ничего не стоят. Вообще. Ничего. Ноль.

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

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

Daniil Tutubalin

unread,
Mar 8, 2010, 9:42:47 AM3/8/10
to ruf...@googlegroups.com
При 30 fps на каждый кадр выделяется около 33 миллисекунд.
Причём, если мы все их "съедим", то пользователи будут жаловаться:
"ваша флешка съедает 100% процессора".
Так что желательно успевать быстрее.
Если же не уложимся да ещё и потратим лишние 3 миллисекунды (итого
36), то вместо 30 fps будет уже 27. С одной стороны тоже неплохо, с
другой стороны - на 3 кадра меньше.
То есть 3 миллисекунды - не такая уж и ерунда.

Теперь по поводу итераций.
Обработка картинки размером 800x600 - это 480 000 итераций. То есть
всего двое меньше миллиона.
Понятно дело, что есть фильтры и шейдеры, но они не всемогущи, иногда
приходится использовать AS.

Ivan Dembicki

unread,
Mar 8, 2010, 10:24:45 AM3/8/10
to ruf...@googlegroups.com
Hello Daniil,

> То есть 3 миллисекунды - не такая уж и ерунда.

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

> Обработка картинки размером 800x600 - это 480 000 итераций. То есть
> всего двое меньше миллиона.

- ты привел именно тот пример, когда микрооптимизация имеет хоть
какой-то смысл.
Но есть вторая сторона медали: лишь часть кода может быть
оптимизирована. Не весь. И далеко не факт, что основное количество
тормозов добавляет оптимизируемый код.
Микрооптимизациями скорее всего удастся добиться не более чем 1%-10%
ускорения работы кода, а то и меньше. Т.е. твоя картинка будет
обсчитываться не 30 секунд, а 27-29.
- Есль выигрыш?
- Есть.
- Стоит за него побороться?
- Возможно.
- Решит ли это проблему?
- НЕТ.

Для пользователя 10% разница в ожидании почти незаметна.
Да, в таком случае лучше попробовать оптимизировать, чем нет.
Но проблему это всё-таки не решает.

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

Alex Davydov

unread,
Mar 8, 2010, 11:49:31 AM3/8/10
to ruf...@googlegroups.com
> При оптимизации производительности куда важнее выявить настоящую
> проблему, чем молотить по всему коду микрооптиизациями.

Прекрасно, прекрасно...
Правда, когда я говорю за оптимизацию во Флаше, то имею ввиду изничтожение ненужных хиттестов\онЕнтерФреймов и прочих "тяж0лых" техник, типа разных 3Д-движков, где они на фиг не нужны.
Тут вот игрушку принесли - на сцене ничего не происходит, а процессор в небо и практически все виснет! А все потому, что создатель тупо засунул ВСЮ логику игр в онЕнтерФрейм, который вызывается всегда!.. Высчитывает свои нули. Огромный, длинный, страшный с множественными вложениями и подвызовами онЕнтерФрейм-ов...
Это, собственно, ошибки алгоритмизирования.. А вы мне тут про микрооптимизaции рассказываете... Как не стыдно!

Jivel

unread,
Mar 8, 2010, 12:00:54 PM3/8/10
to ruf...@googlegroups.com
>> При оптимизации производительности куда важнее выявить настоящую
>> проблему, чем молотить по всему коду микрооптиизациями.

> микрооптимизaции рассказываете... Как не стыдно!

Так вроде все правильно сказал - "Какие в жаву оптимизации с алгоритмами
сначала разберитесь." -
Ведь правильно, ведь верно?

---
сорь не удержался =)
http://pics.livejournal.com/gaperton/pic/00003fx1

Daniil Tutubalin

unread,
Mar 8, 2010, 6:15:21 PM3/8/10
to ruf...@googlegroups.com
function test() {
var arr = new Array();
arr[1000] = new Point();

var sum = 0;
var time = getTimer();
for (var i=0; i<arr.length; i++) {
try {
sum += arr[i].x;
} catch (error:Error) {}
}
trace (getTimer()-time);

}

test();


На моей машинке пишет 6-7 миллисекунд.
А это всего один цикл, причём по массиву, в котором всего один элемент.
В больших проектах таких циклов может быть много.
Разряжённые массивы - не такая уж и редкая вещь.
Т.е. в принципе, вполне реальный пример. 6 миллисекунд.
Если заменить try...catch на if, то время выполнения падает до 0
миллисекунд. Солидный выигрыш.

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

Reply all
Reply to author
Forward
0 new messages