JVM neden hala arama optimizasyonunu desteklemiyor?


95

Jvm-önleme-çağrı-optimizasyonlarından iki yıl sonra , bir prototip uygulaması var gibi görünüyor ve MLVM bir süredir bu özelliği "proto% 80" olarak listeliyor.

Kuyruk çağrıları desteklenmesinde Sun'ın / Oracle'ın taraftan etkin faiz var mı yoksa kuyruk aramalar sadece "[...] öyle her özellik öncelik listesinde ikinci sırada gelmeye kader [...]" nde belirtildiği gibi JVM Dil Zirvesi ?

Birisi bir MLVM yapısını test ettiyse ve (eğer varsa) ne kadar iyi çalıştığına dair bazı izlenimleri paylaşabilseydi gerçekten ilgilenirim.

Güncelleme: Avian gibi bazı VM'lerin herhangi bir sorun olmadan uygun kuyruk aramalarını desteklediğini unutmayın .


14
Sun insanlarının Oracle'dan göç ettiği bildirildiğinden, Oracle'dan açıkça belirtilmedikçe mevcut projelerden hiçbirinin devam etmesini beklemiyorum :(
Thorbjørn Ravn Andersen

16
Kabul ettiğiniz cevabın tamamen yanlış olduğunu unutmayın. Kuyruk çağrısı optimizasyonu ile OOP arasında temel bir çelişki yoktur ve tabii ki OCaml ve F # gibi birkaç dilde hem OOP hem de TCO vardır.
JD

2
OCaml ve F # OOP dillerini aramak ilk etapta kötü bir şaka. Ancak evet, OOP ve TCO'nun pek ortak yanı yoktur, ancak çalışma zamanının optimize edilen yöntemin başka bir yerde geçersiz kılınmadığını / alt sınıflara alınmadığını kontrol etmesi gerektiği gerçeği dışında.
soc

5
+1 C geçmişinden geldiğimde, her zaman TCO'nun herhangi bir modern JVM'de verildiğini varsaydım. Gerçekten kontrol etmek hiç aklıma gelmemişti ve yaptığımda sonuçlar şaşırtıcıydı ...
thkala

2
@soc: "çalışma zamanının optimize edilen yöntemin başka bir yerde geçersiz kılınmadığını / alt sınıflara alınmadığını kontrol etmesi gerektiği gerçeği dışında". Senin "gerçeğin" tamamen saçmalık.
JD

Yanıtlar:


33

Java Kodunu Teşhis Etme: Java Kodunuzun Performansını İyileştirme ( alt ), JVM'nin neden kuyruk arama optimizasyonunu desteklemediğini açıklar.

Ancak, bir kuyruk özyinelemeli işlevin otomatik olarak basit bir döngüye nasıl dönüştürüleceği iyi bilinmesine rağmen, Java belirtimi bu dönüşümün yapılmasını gerektirmez. Muhtemelen, bunun bir gereklilik olmamasının bir nedeni, genel olarak dönüşümün nesne yönelimli bir dilde statik olarak yapılamamasıdır. Bunun yerine, kuyruk özyinelemeli işlevden basit döngüye dönüşüm, bir JIT derleyicisi tarafından dinamik olarak yapılmalıdır.

Daha sonra dönüşmeyecek bir Java kodu örneği verir.

Bu nedenle, Liste 3'teki örneğin gösterdiği gibi, statik derleyicilerin dilin anlamını korurken Java kodunda kuyruk özyinelemesinin dönüşümünü gerçekleştirmesini bekleyemeyiz. Bunun yerine, JIT'in dinamik derlemesine güvenmeliyiz. JVM'ye bağlı olarak, JIT bunu yapabilir veya yapmayabilir.

Ardından, JIT'inizin bunu yapıp yapmadığını anlamak için kullanabileceğiniz bir test verir.

Doğal olarak, bu bir IBM kağıdı olduğu için bir fiş içerir:

Bu programı birkaç Java SDK ile çalıştırdım ve sonuçlar şaşırtıcıydı. Sun'ın 1.3 sürümü için Hotspot JVM'sini çalıştırmak, Hotspot'un dönüşümü gerçekleştirmediğini ortaya koyuyor. Varsayılan ayarlarda, yığın alanı makinemde bir saniyeden daha kısa sürede tükeniyor. Öte yandan, IBM'in 1.3 sürümü için JVM'si, kodu bu şekilde dönüştürdüğünü göstererek sorunsuz bir şekilde devam ediyor.


63
FWIW, kuyruk aramaları, onun ima ettiği gibi sadece kendi kendini yineleyen işlevlerle ilgili değildir. Kuyruk aramaları, kuyruk konumunda görünen herhangi bir işlev çağrısıdır. Kendi kendine çağrı olmaları gerekmez ve statik olarak bilinen konumlara çağrı olmaları gerekmez (örneğin, sanal yöntem çağrıları olabilirler). Açıkladığı sorun, genel durumda kuyruk arama optimizasyonu düzgün bir şekilde yapılırsa sorun olmaz ve sonuç olarak, onun örneği, kuyruk çağrılarını destekleyen nesne yönelimli dillerde mükemmel çalışır (örn. OCaml ve F #).
JD

3
"JIT derleyicisi tarafından dinamik olarak yapılmalıdır", yani Java derleyicisi yerine JVM'nin kendisi tarafından yapılmalıdır. Ancak OP, JVM hakkında soru soruyor.
Raedwald

11
"genel olarak, nesne yönelimli bir dilde dönüşüm statik olarak yapılamaz." Bu elbette bir alıntıdır, ancak bu tür bir mazereti her gördüğümde sayılar hakkında soru sormak isterim - çünkü pratikte çoğu durumda derleme zamanında tespit edilebilirse şaşırmam.
greenoldman

5
Google'ın önbelleğe almasına rağmen, alıntı yapılan makalenin bağlantısı artık kesildi. Daha da önemlisi, yazarın mantığı hatalı. Verilen örnek olabilir kuyruk çağrı statik kullanılarak optimize edilmiş ve olmak değil , sadece derleyici bir takılıysa, sadece dinamik derleme instanceofolmadığını görmek için kontrol thisbir olan Examplenesne (ziyade bir alt sınıf arasında Example).
Alex D


30

Geçmişte Java'da TCO uygulamamasının (ve bunun zor görülmesinin) bir nedeni, JVM'deki izin modelinin yığına duyarlı olması ve bu nedenle kuyruk aramalarının güvenlik yönlerini ele alması gerektiğidir.

Bunun Clements ve Felleisen [1] [2] tarafından bir engel olmadığını gösterdiğine inanıyorum ve soruda bahsedilen MLVM yamasının da bununla ilgilendiğinden eminim.

Bunun sorunuza cevap vermediğini fark ediyorum; sadece ilginç bilgiler ekliyor.

  1. http://www.ccs.neu.edu/scheme/pubs/esop2003-cf.pdf
  2. http://www.ccs.neu.edu/scheme/pubs/cf-toplas04.pdf

2
+1. Brian Goetz'in bu sunumunun sonundaki soruları / yanıtları dinleyin youtube.com/watch?v=2y5Pv4yN0b0&t=3739
mcoolive

15

Belki bunu zaten biliyorsunuzdur, ancak özellik, göründüğü kadar önemsiz değildir çünkü Java dili aslında yığın izini programcıya gösterir.

Aşağıdaki programı düşünün:

public class Test {

    public static String f() {
        String s = Math.random() > .5 ? f() : g();
        return s;
    }

    public static String g() {
        if (Math.random() > .9) {
            StackTraceElement[] ste = new Throwable().getStackTrace();
            return ste[ste.length / 2].getMethodName();
        }
        return f();
    }

    public static void main(String[] args) {
        System.out.println(f());
    }
}

Bunun bir "kuyruk çağrısı" olmasına rağmen optimize edilmemiş olabilir. (Bu takdirde edilir optimize, hala programın buna dayanır semantik beri tüm çağrı-yığının defter tutma gerektirir.)

Temel olarak, bu, hala geriye dönük uyumluyken bunu desteklemenin zor olduğu anlamına gelir.


17
Düşüncenizdeki hatayı buldum: "programın anlamsallığı ona bağlı olduğundan tüm çağrı yığınının tutulmasını gerektirir". :-) Yeni "bastırılmış İstisnalar" gibi. Bu tür şeylere dayanan programlar bozulmaya mahkumdur. Kanımca programın davranışı kesinlikle doğrudur: Yığın çerçevelerini atmak, kuyruk çağrılarının tümüyle ilgili olduğu şeydir.
soc

4
@Marco, ancak hemen hemen her yöntem, tüm çağrı yığınının mevcut olması gereken bir istisna atabilir, değil mi? Ayrıca, gbu durumda hangi yöntemlerin dolaylı olarak çağıracağına önceden karar veremezsiniz ... örneğin polimorfizm ve yansımayı düşünün.
aioobe

2
Java 7'de ARM eklenmesinin neden olduğu bir yan etkidir. Yukarıda gösterdiğiniz bu tür şeylere güvenemeyeceğinize bir örnektir.
soc

6
"dil çağrı yığını ortaya gerçeği zor uygulamak için yapar bu" dil gerektiren olmadığını tarafından döndürülen yığın-iz getStackTrace()bir yöntemden x()kaynak kod gösterileri yönteminden denir y()da gösteriler x()çağrıldı y()? Çünkü biraz özgürlük varsa gerçek bir sorun yok.
Raedwald

8
Bu sadece tek bir yöntemin spesifikasyonunu ifade etme meselesidir, "size tüm yığın çerçevelerini verir" den "size tüm aktif yığın çerçevelerini verir, kuyruk çağrıları tarafından kullanılmayanları dışarıda bırakır". Dahası, kuyruk çağrısının kabul edilip edilmediğini bir komut satırı anahtarı veya bir sistem özelliği yapabilir.
Ingo

12

Java, hayal edebileceğiniz en az işlevsel dildir (pekala, tamam, belki hayır !), Ancak bu, Scala gibi JVM dilleri için büyük bir avantaj olacaktır .

Gözlemlerim, JVM'yi diğer diller için bir platform haline getirmenin, Sun için öncelik listesinin başında hiç görünmedi ve sanırım şimdi Oracle için.


16
@ Thorbjørn - Herhangi bir programın sınırlı bir süre içinde durup durmayacağını tahmin etmek için bir program yazdım. Bu götürdü yaş !
oxbow_lakes

3
Kullandığım ilk BASIC'lerin işlevleri yoktu, bunun yerine GOSUB ve RETURN. LOLCODE'un da çok işlevsel olduğunu düşünmüyorum (ve bunu iki anlamda anlayabilirsiniz).
David Thornley

1
@David, işlevsel! = İşlevlere sahiptir.
Thorbjørn Ravn Andersen

2
@ Thorbjørn Ravn Andersen: Hayır, ama bu bir tür ön koşul, değil mi?
David Thornley

3
"JVM'yi diğer diller için bir platform haline getirmek hiçbir zaman Sun için öncelik listesinin başında görünmedi". JVM'yi dinamik diller için bir platform haline getirmek için işlevsel diller için yaptıklarından çok daha fazla çaba harcadılar.
JD
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.