2015-06-01 15 views
6

Bu kriter java8-lambda-performance-test kullanmış ve bunu çalıştırırken ben şunları yaptım:Intrinsics'in etkisi ve Lambda'nın performansındaki çizgiyi?

1.Disabled İçsel kullanım

2.Disabled Satır içi

3.Disabled Derleme modu

ben İlk iki optimizasyonu devre dışı bırakmanın sonuçlara etkisi olmadığını bulduk. matematik intrinsics ağır orada _min kullanıldığından ile kriter ve içsel baskı çalıştırırken de garip ve

, ben _pow ... bunu bekliyordum, içsel compiledLambdaForm

için herhangi bir çağrı bulamadık Lambda ifadeleri inlining ve intrinsics hem lambda kendisi üzerinde bir etkisi yoktur bu yüzden Yani esas sınıfı LambdaMetaFactory. kullanması nedeniyle devre dışı intrinsics, slown performansını

+1

Sonuçlarınızın güzel ifadeleri. Eğer bu bir problemse, neden açıkça ve neyi beklediğinizi açıkça belirtin. Aksi halde sorun görmedim. –

+0

Gönderiyi düzenledim – Bionix1441

+0

Makaleye bir göz atmak, söyleyebildiğim çok eski olduğunu söyledi (Mar 17, 2014). Bu yazıdan bu yana Java 8 güncellemesi olabilir. Eğer yazar tarafından kullanılana farklı bir JVM sürümü kullanıyorsanız (ki o bunu belirtmez), testinizin farklı sonuçlar göstermesi oldukça anlaşılır bir durumdur. Erken bir Java 8 kullanmayı deneyin ve bunun herhangi bir fark yaratıp yaratmadığını görün. –

cevap

4

Beklenen bir performans etkisini fark etmemenizin nedeni poorly written benchmark.
JMH kullanarak benchmark yazdım ve nihayet doğru olan şeyler.

Beklendiği gibi
Benchmark        Mode Cnt  Score Error Units 
LambdaBenchmark.streamAverage   avgt 5 71,490 ± 0,770 ms/op 
LambdaBenchmark.streamAverageNoInline avgt 5 122,740 ± 0,576 ms/op 
LambdaBenchmark.streamMath    avgt 5 92,672 ± 1,538 ms/op 
LambdaBenchmark.streamMathNoIntrinsic avgt 5 5747,007 ± 20,387 ms/op 

, -XX:-Inline ile kıyaslama artık% 70 çalışır ve Matematik ile versiyon intrinsics engelli 60 kat daha yavaş gibi görünen: Burada

package lambdademo; 

import org.openjdk.jmh.annotations.*; 

import java.util.List; 

@State(Scope.Benchmark) 
public class LambdaBenchmark { 
    @Param("100") 
    private static int loopCount; 

    private static double identity(double val) { 
     double result = 0; 
     for (int i=0; i < loopCount; i++) { 
      result += Math.sqrt(Math.abs(Math.pow(val, 2)));  
     } 
     return result/loopCount; 
    } 

    private List<EmployeeRec> employeeList = new EmployeeFile().loadEmployeeList(); 

    @Benchmark 
    public double streamAverage() { 
     return streamAverageNoInline(); 
    } 

    @Benchmark 
    @Fork(jvmArgs = "-XX:-Inline") 
    public double streamAverageNoInline() { 
     return employeeList.stream() 
       .filter(s -> s.getGender().equals("M")) 
       .mapToDouble(s -> s.getAge()) 
       .average() 
       .getAsDouble(); 
    } 

    @Benchmark 
    public double streamMath() { 
     return streamMathNoIntrinsic(); 
    } 

    @Benchmark 
    @Fork(jvmArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:DisableIntrinsic=_dpow,_dabs,_dsqrt"}) 
    public double streamMathNoIntrinsic() { 
     return employeeList.stream() 
       .filter(s -> s.getGender().equals("M")) 
       .mapToDouble(s -> identity(s.getAge())) 
       .average() 
       .getAsDouble(); 
    } 
} 

sonuçlardır!

+0

Bir soru: Neden 'private static int loopCount = Integer.getInteger kodladınız ("loopCount", 100); 'int loopCount = 100;' – Bionix1441

+2

yerine, ayrıca no @ @ Param'? Statik alanlarda da çalışır. –

+2

@ Bionix1441 Bunun için belirli bir nedeni yok. Her iki şekilde de yapacak. @AlekseyShipilev Sağ, 'Param' daha iyidir. Kodu güncelledim. – apangin

1

Ben intrinsics herhangi bir etkisi var olduğunu düşünmüyorum olurdu.

Şimdi içsel matematik için benim inancım, sadece LambdaExtraAverage ve LambdaExtraSerial testlerinde kullanılan sadece kimlik yönteminde kullanıldığı için, o zaman karşılaştırma sonuçlarını etkilemeyecekleridir.