Текущий архив: 2007.11.04;
Скачать: CL | DM;
Вниз
Это нормально? Найти похожие ветки
← →
pasha_golub © (2007-10-04 11:50) [40]
> vpbar © (04.10.07 10:22) [32]
> Ниже приведены их результаты и результаты выполнения нашего
> нового Float-теста.
Так вопрос об оптимизаторе поднимался. Кроме float есть весомые аргументы?
> jack128_ (04.10.07 10:32) [35]
>
> http://www.rsdn.ru/article/devtools/perftest.xml
Жень по ссылке твоей:
> Выводы по тесту
> В этом тесте выиграл не самый быстрый компилятор, а средство
> разработки, в котором серьезно подошли к переписыванию функций
> управления памятью.
← →
Sandman31 (2007-10-04 12:22) [41]euru © (04.10.07 11:48) [39]
В java нет невиртуальных методов, то есть адрес даже final-метода определяется по таблице методов. Да и как иначе, ведь final-метод может быть изменен в новой версии класса и использоваться другим классом, использоваться рефлекшн и т.д. Так что единственная оптимизация - подстановка тела метода вместо вызова private final, тогда вообще нет никакого метода.
← →
euru © (2007-10-04 14:07) [42]
> Sandman31 (04.10.07 12:22) [41]
Java Language Specification
8.4.3.3 final Methods
A method can be declaredfinal
to prevent subclasses from overriding or hiding it. It is a compile-time error to attempt to override or hide afinal
method.
. . .
At run time, a machine-code generator or optimizer can "inline" the body of afinal
method, replacing an invocation of the method with the code in its body.
← →
Sandman31 (2007-10-04 14:22) [43]euru © (04.10.07 14:07) [42]
Я об этом и говорил.Contrary to the implication of many tips, methods declared as final cannot be safely inlined by the compiler, because the method could have a non-final declaration at runtime.
To see why, suppose the compiler looks at class A and subclass B, and sub-subclass C and sees a final method in A which it inlines into C. But then at runtime the versions loaded for A and B are different and the method is not final in A, and overridden in B. Then C uses the incorrectly inlined version. This was a bug in some of the early compilers when used with the -O option. So tips suggesting using final and the -O option are not valid tips.
On the other hand, final methods can be inlined after being loaded into the JVM, because at that point the JVM knows definitely that the method is final. So compilers that operate after class loading, such as JIT compilers, can take advantage of final methods. Consequently, methods declared final could have some performance benefit.
Generally, I wouldn"t go out of my way to declare a method or class final purely for performance reasons. Only after you"ve definitely identified a performance problem is this even worth considering.
http://www.javaperformancetuning.com/tips/final.shtmlFor Performance?
Since a final method is only implemented in the declaring class, there is no need to dynamically dispatch a call to a final method, and static invocation can be used instead. The compiler can emit a direct call to the method, bypassing entirely the usual virtual method invocation procedure. Because of this, final methods are also candidates for inlining by a Just-In-Time compiler or a similar optimization tool. (Remember, private/static methods are already final, therefore always considered for this optimization.)
Static invocation is faster than dynamic method lookup, leading to the widespread use of final methods as an optimization technique. But this "optimization" is next to useless in recent virtual machines: they are able to detect if a non-final method is overridden, and if not, use static invocation. Therefore, final should be used first and foremost for sofware engineering reasons, as discussed in the rest of this article.
http://renaud.waldura.com/doc/java/final-keyword.shtml#methods
← →
euru © (2007-10-04 16:29) [44]
> Sandman31 (04.10.07 14:22) [43]
Фразыадрес даже final-метода определяется по таблице методов
иthere is no need to dynamically dispatch a call to a final method, and static invocation can be used instead
мне кажется, несколько противоречат друг другу.
← →
Sandman31 (2007-10-04 16:52) [45]euru © (04.10.07 16:29) [44]
Static invocation в java означает, что не будет осуществляться поиск конкретного класса, метод которого будет вызван, потому что класс уже точно известен. Но поиск расположения кода метода по таблице методов всё равно будет, потому что на момент вызова точка входа в метод кода может быть неизвестен (очевидно в случае вызова метода любого другого класса, кроме собственного).
На java в принципе невозможно передать управление на N байт вниз, как в случае static invocation в C или Delphi.
← →
Sandman31 (2007-10-04 17:19) [46]ИМХО налицо некоторая двусмысленность термина виртуальный.
Вот например:class A {
public void method() {}
}
Является ли метод виртуальным? Несомненно.class B extends A {
public final void method() {}
}
А теперь? А будет ли dynamic invocation из anotherMethod в случае:class B extends A {
public final void method() {}
public void anotherMethod(){
...
method();
...
}
}
у хорошей JVM не будет.
А в случаеA a = ..
a.method()
Даже у хорошей JVM будет.
А будет ли dynamic invocation в случаеclass C {
void myMethod(){
B b = ...
b.method();
}
}
Не знаю. C одной стороны ясно, что метод находится именно в классе B, но с другой стороны inline не сделать в принципе.
← →
Sandman31 (2007-10-04 17:29) [47]А вообще похоже, что я неправ. Судя по http://www.research.ibm.com/journal/sj/391/suganuma.html
private и static методы действительно называют nonvirtual.
← →
vpbar © (2007-10-04 21:05) [48]К вопросу об оптимизации.
Сравнение эффективности оптимизатора
Тестируемый код. Привожу варинт на делфи, на С++ код идентичен этому.procedure TestIfThen;
var flag: Boolean;
j:integer;
begin
asm jmp @@end; db $AD,$CB,$EF,$10; @@end: end;
QueryPerformanceCounter(TimeStart);
for j := 0 to LoopCount do
begin
if j > 2 then
begin
if LoopCount > j * 2 then
begin
flag := false;
res := (LoopCount + res) div divr;
end else
begin
flag := true;
res := (LoopCount + res) div divr;
end;
end else
begin
res := (LoopCount + res) div divr;
end;
end;
if flag then res := res + LoopCount * t else res := res - LoopCount * t;
QueryPerformanceCounter(TimeEnd);
OutResult("TestIfThen");
asm jmp @@end; db $AD,$CB,$EF,$11; @@end: end;
end;
procedure Sampl(a,b:integer);
begin
res:=a+b;
asm jmp @@end; db $AD,$CB,$EF,$12; @@end: end;
end;
procedure TestCall;
var flag: Boolean;
j:integer;
begin
asm jmp @@end; db $AD,$CB,$EF,$13; @@end: end;
QueryPerformanceCounter(TimeStart);
for j := 0 to LoopCount do
begin
if j > 2 then
Sampl(divr*2+LoopCount*2,j+LoopCount)
else
Sampl(divr*2+LoopCount*2,j-LoopCount);
end;
QueryPerformanceCounter(TimeEnd);
OutResult("TestCall");
asm jmp @@end; db $AD,$CB,$EF,$14; @@end: end;
end;
procedure TestCall2;
var flag: Boolean;
j:integer;
r:TRect;
begin
asm jmp @@end; db $AD,$CB,$EF,$15; @@end: end;
QueryPerformanceCounter(TimeStart);
for j := 0 to LoopCount do
begin
if j > 2 then
OffsetRect(r,divr*2+LoopCount*2,j+LoopCount)
else
OffsetRect(r,divr*2+LoopCount*2,j-LoopCount);
end;
QueryPerformanceCounter(TimeEnd);
OutResult("TestCall2");
asm jmp @@end; db $AD,$CB,$EF,$16; @@end: end;
end;
Список результатов. В скобках опции оптимизатора.
Delphi 7 (optimization)
TestIfThen Time: 26,6
TestCall Time: 16,5
TestCall2 Time: 9,7
****************************
Delphi 7 (no optimization)
TestIfThen Time: 26,9
TestCall Time: 9,7
TestCall2 Time: 21,7
****************************
Borland Developer Studio 2006 (optimization)
TestIfThen Time: 26,4
TestCall Time: 15,3
TestCall2 Time: 10,2
****************************
Borland Developer Studio 2006 (no optimization)
TestIfThen Time: 28,4
TestCall Time: 10,2
TestCall2 Time: 19,6
****************************
Microsoft Visual Studio 2005 (Maximize Speed (/O2))
TestIfThenTime: 2.7
TestCallTime: 4.5
TestCall2Time: 9.0
****************************
Microsoft Visual Studio 2005 (Disabled (/Od))
TestIfThenTime: 28.5
TestCallTime: 9.5
TestCall2Time: 11.8
****************************
MiniGW Studio 2.05 (Level3)
TestIfThenTime: 25.4
TestCallTime: 2.2
TestCall2Time: 8.7
****************************
MiniGW Studio 2.05 (None)
TestIfThenTime: 29.4
TestCallTime: 9.0
TestCall2Time: 13.0
Интересно что в Делфях неоптимизированный вариант TestCall работает быстрее.
Такая вот "оптимизация" в Делфях.
Лучшие результаты Visual Studio 2005 обусловлены тем, что ее
копмилятор выносит общие выражения из цикла.
Тесты конечно очень синтетические (хотя первая процедура по мотивам реального кода), но различие компиляторов показывают.
ЗЫ. Где-то встречал анализ методов оптимизации (вынос общего, развертка циклов, использование быстрых комманд) и наличия их в распростроненных компиляторах. Если найду - покажу иначе сам на досуге проанализирую и все равно покажу.
← →
euru © (2007-10-05 10:50) [49]
> Sandman31 (04.10.07 17:19) [46]
> А будет ли dynamic invocation в случае
> class
> {
> void myMethod(){
> B b = ...
> b.method();
> }
>
> Не знаю. C одной стороны ясно, что метод находится именно в классе B,
> но с другой стороны inline не сделать в принципе.
А почему нельзя в принципе? Ведь с точки зрения спецификации языка здесь, в отличие от примера, приведённого выше этого примера, однозначно вызовется метод класса В и никакой другой.
← →
Sandman31 (2007-10-05 11:03) [50]euru © (05.10.07 10:50) [49]
А почему нельзя в принципе? Ведь с точки зрения спецификации языка здесь, в отличие от примера, приведённого выше этого примера, однозначно вызовется метод класса В и никакой другой.
Да, вызовется именно B.method. Но нет никакой гарантии, что в run-time класс B будет тот же самый, что и при компиляции класса C. Никто мне не мешает изменить класс B без перекомпиляции класса С, в котором он используется, при условии, что сигнатура методов класса B не поменяется.
← →
2463A7C8 (2007-10-07 22:12) [51]Если же случалась большая беда — телепередачи показывали иногда катастрофы с
повозками или летательными аппаратами, — то немедленно собиралась толпа.
Страницы: 1 2 вся ветка
Текущий архив: 2007.11.04;
Скачать: CL | DM;
Память: 0.58 MB
Время: 0.021 c