Вызов метода интерфейса требует больше времени, чем вызов метода класса. Вопрос: насколько больше в современных виртуальных машинах с JIT-компиляцией и кэшированием классов? Есть ли где-нибудь исследования на эту тему?
Например, я часто, не задумываясь, пишу следующий код:
// описание локальной переменнойfinal List l = new ArrayList();
// переменная используется в ограниченной области видимости
Насколько снижает эффективность то, что переменная l определена через интерфейс, а не явный класс?
Здравствуйте, Аноним, Вы писали:
M>>>>В time-critical коде надо проверять производительность, а лучше сразу писать виртуальные (а ещё лучше — final) методы.
_>>>Поясните, пожалуйста, где писать?
GIV>>Значит нигде не надо. Совершенно серьезно, не заморачивайся.
А>может все таки развернете тему или дадите источник, где данное описываеться.
Источник тут только один — измерения (профайлер или еще что). Если ты здаешь этот вопрос значит не имеешь этой информации — ничего не надо делать.
А>и 1.5 раза это разве мало?? О_о
Это не много и не мало — это ни о чем. Еслиб от этого программа работала в полтора раза быстрее...
Ты лучше посчитай сколько это в абсолютных величинах, в % выполнения какого нибудь бизнес действия\запроса\чем там твоя прога занимается.
При нынешнем количестве рефлекшена и разного рода экспрешенов волноваться о сабже это как-то неприлично даже
Разве что на телефонах и реалтайм системах это может представлять интерес.
Здравствуйте, andrey_nado, Вы писали:
_>Вызов метода интерфейса требует больше времени, чем вызов метода класса. Вопрос: насколько больше в современных виртуальных машинах с JIT-компиляцией и кэшированием классов? Есть ли где-нибудь исследования на эту тему?
В современной яве оверхед совсем небольшой (где-то раза в полтора). Но это очень зависит от количества классов, которые имплементят интерфейс.
В time-critical коде надо проверять производительность, а лучше сразу писать виртуальные (а ещё лучше — final) методы.
В остальном коде заморачиваться совершенно не имеет смысла.
Здравствуйте, mkizub, Вы писали:
M>В time-critical коде надо проверять производительность, а лучше сразу писать виртуальные (а ещё лучше — final) методы.
Здравствуйте, andrey_nado, Вы писали:
M>>В time-critical коде надо проверять производительность, а лучше сразу писать виртуальные (а ещё лучше — final) методы.
_>Поясните, пожалуйста, где писать?
Значит нигде не надо. Совершенно серьезно, не заморачивайся.
WBR, Igor Evgrafov
Re[4]: Интерфейс vs. Класс: производительность
От:
Аноним
Дата:
02.03.10 19:37
Оценка:
Здравствуйте, GarryIV, Вы писали:
GIV>Здравствуйте, andrey_nado, Вы писали:
M>>>В time-critical коде надо проверять производительность, а лучше сразу писать виртуальные (а ещё лучше — final) методы.
_>>Поясните, пожалуйста, где писать?
GIV>Значит нигде не надо. Совершенно серьезно, не заморачивайся.
может все таки развернете тему или дадите источник, где данное описываеться.
Здравствуйте, andrey_nado, Вы писали:
_>Насколько снижает эффективность то, что переменная l определена через интерфейс, а не явный класс?
А ты прикинь сколько тысяч раз в секунду у тебя идет обращение к этому списку. Тогда можно оценить выигрыш от подобной микро оптимизации, если разница и правда такая большая.
On 03/03/2010 01:37 AM, Аноним 404 wrote: > может все таки развернете тему или дадите источник, где данное описываеться.
Первое: Классы, Интерфейсы, Типы, полиморфизм — все это инструменты
проектирования, а производительность определяется реализацией. Поэтому
нужно использовать то, что позволяет облегчить проектирование, и ни в
коем случае не выбирать тип переменной исходя из скорости работы.
Второе: реализация полностью "на совести" JRE. Ни одна JRE не может
обещать, что доступ к объекту через ссылку одного типа будет быстрее
(или медленнее) чем доступ к тому же объекту через ссылку другого типа.
То есть опираться на такие "обещания" в целях оптимизации нельзя.
Третье: программы на языке ява один раз компилируются в байт код (и
может произойти оптимизация которая заменит способы адресации не меняя
семантики), и второй раз уже байт-код может компилироваться в машинные
коды, что скорее всего приведет к замене адресации. То есть нельзя
сказать что вызов list.size(); в машинных кодах будет отличаться для
разных типов переменной list. А также нельзя сказать что для одного и
того же типа переменной list вызов list.size() в машинных кодах будет
одинаковым.
Четвертое: Ситуация когда ЭТО важно. Скорость работы программы при
использовании переменных разных типов важна разработчикам JRE. Если вы
пишете JRE — тут и гадать нечего. Сделайте чтобы обращение через любой
интерфейс занимало как можно меньше машинных тактов. Вот и все.
On 03/03/2010 01:54 AM, Blazkowicz wrote: > А ты прикинь сколько тысяч раз в секунду у тебя идет обращение к этому > списку. Тогда можно оценить выигрыш от подобной микро оптимизации, если > разница и правда такая большая.
Может быть лучше улучшать оптимизацию путем уменьшения этих "сколько
тысяч раз в секунду"?
Здравствуйте, Аноним, Вы писали:
А>и 1.5 раза это разве мало?? О_о
Да. Просто надо понимать 1.5 раза от чего. К примеру 1.5 раза от ноля по прежнему будет ноль.
Имеется в виду 1.5 раза на вызов самомго метода, без учёта кода самого метода. Если вызывать только пустые методы — то да, замедление может стать существенным. Но, как правило, методы всё-таки что-то делают, иначе нафига их вызывать то?
В общем, на современных JVM, это такая микрооптимизация, что прибегать к ней стоит только в последнюю очередь, когда остальные способы уже испробованы, а профайлер всё равно показывает на это место.
Здравствуйте, andrey_nado, Вы писали:
_>Вызов метода интерфейса требует больше времени, чем вызов метода класса. Вопрос: насколько больше в современных виртуальных машинах с JIT-компиляцией и кэшированием классов? Есть ли где-нибудь исследования на эту тему?
В интернетах есть все
Например здесь и продолжениездесь
как правильно заметил mkizub тут все зависит от развесистости иерархии наследования.
Здравствуйте, Donz, Вы писали:
D>Заверяю, такой фигней не маятся даже на телефонах с J2ME
Думаю маятся, и еще как.
Вот для Android даже есть специальный раздел в документации, где пишут сколько стоит какой вызов.
Ты хочешь сказать что для игры совсем не важно это?
Здравствуйте, techgl, Вы писали:
D>>Заверяю, такой фигней не маятся даже на телефонах с J2ME T>Думаю маятся, и еще как.
Как бывший разработчик J2ME игр заверяю, что абсолютное большинство ресурсов съедает отрисовка графики. На втором месте обсчет логики, если она в игре не тривиальная.
Правда, в первую очередь проблема "Интерфейсы vs сразу классы" не стояла, потому что для оптимизации размера джара классов было три штуки: мидлет, канвас со всем, что только можно внутри и вспомогательный класс-тайл.
T>Вот для Android даже есть специальный раздел в документации, где пишут сколько стоит какой вызов. T>Ты хочешь сказать что для игры совсем не важно это?
Если нетривиальная логика, то, наверное, раздутая иерархия классов может играть роль, особенно, если большая часть вызовов — это геттеры/сеттеры. Если метод делает нечто более полезное, то, как уже сказали, на этом фоне разница в вызовах будет на уровне погрешности измерений.
В игре "Пасьянс Маджонг" может быть до полутора сотен костей на поле. При каждой отрисовке надо по всем ним пробежаться, чтобы понять, а надо ли перерисовать кость, чтобы на ней не осталось следов курсора. Сделав инлайн одного метода, который вызывался полторы сотни раз за одну перерисовку, я получил повышение производительности что-то около 2-5%.
Здравствуйте, Donz, Вы писали:
D>Если нетривиальная логика, то, наверное, раздутая иерархия классов может играть роль, особенно, если большая часть вызовов — это геттеры/сеттеры. Если метод делает нечто более полезное, то, как уже сказали, на этом фоне разница в вызовах будет на уровне погрешности измерений.
Про J2ME речь вообще не шла, так как в ней оптимизация вызова интерфейсов не делается. Ищут по таблице методов, с кэшированием последнего найденного.
Развесистось иерархии классов в J2ME до лампочки — память не позволяет делать оптимизации уровня HotSpot-а.
Здравствуйте, mkizub, Вы писали:
M>Про J2ME речь вообще не шла, так как в ней оптимизация вызова интерфейсов не делается. Ищут по таблице методов, с кэшированием последнего найденного.
Я просто привел пример, по которому можно судить о подобной оптимизации. KVM все-таки имеет что-то общее с обычной JVM
M>Развесистось иерархии классов в J2ME до лампочки — память не позволяет делать оптимизации уровня HotSpot-а.
Можно подробнее?
Во многих реализациях CLDC 1.1 используется как раз HotSpot. Я так понимаю, не в полной мере, как в большой яве?
Здравствуйте, Donz, Вы писали:
M>>Развесистось иерархии классов в J2ME до лампочки — память не позволяет делать оптимизации уровня HotSpot-а. D>Можно подробнее? D>Во многих реализациях CLDC 1.1 используется как раз HotSpot. Я так понимаю, не в полной мере, как в большой яве?
У него столько же общего с J2SE HotSpot-ом, сколько у J2ME общего с J2SE. Название.
На мобилках просто нет ресурсов, ни по памяти, ни по CPU, для таких оптимизаций, которые делает десктопный JIT.
Здравствуйте, mkizub, Вы писали:
D>>Во многих реализациях CLDC 1.1 используется как раз HotSpot. Я так понимаю, не в полной мере, как в большой яве?
M>У него столько же общего с J2SE HotSpot-ом, сколько у J2ME общего с J2SE. Название.
Значит не так уж и мало
M>На мобилках просто нет ресурсов, ни по памяти, ни по CPU, для таких оптимизаций, которые делает десктопный JIT.
Так каких таких? О чем говорит надпись Hotspot Implementation при указании версии CLDC?