JVM, kuyruk arama optimizasyonlarını engelliyor mu?


99

Şu soru üzerinde şu alıntıyı gördüm: Bir web hizmetinin üzerine inşa edilecek iyi bir işlevsel dil nedir?

Özellikle Scala, yapabileceğiniz kompozisyon türlerini sınırlayan kendi kendine özyinelemeli işlevler dışında kuyruk çağrısı ortadan kaldırmayı desteklemez (bu JVM'nin temel bir sınırlamasıdır).

Bu doğru mu? Eğer öyleyse, bu temel sınırlamayı yaratan JVM ile ilgili nedir?

Yanıtlar:


74

Bu gönderi: Özyineleme mi, Yineleme mi? yardımcı olabilir.

Kısacası, güvenlik modeli ve her zaman bir yığın izlemeye sahip olma ihtiyacı nedeniyle JVM'de kuyruk araması optimizasyonu yapmak zordur. Bu gereksinimler teoride desteklenebilir, ancak muhtemelen yeni bir bayt kodu gerektirecektir ( John Rose'un gayri resmi önerisine bakın ).

Ayrıca, değerlendirmenin (2002'den itibaren) sona erdiği Sun bug # 4726340'ta daha fazla tartışma var :

Yine de bunun yapılabileceğine inanıyorum, ancak bu küçük bir görev değil.

Şu anda Da Vinci Makinesi projesinde devam eden bazı çalışmalar var . Kuyruk arama alt projesinin durumu "proto% 80" olarak listelenir; Java 7'ye dönüşmesi pek olası değil, ancak Java 8'de çok iyi bir şansı olduğunu düşünüyorum.


Açıklamayı tam olarak takip etmedim. Kuyruk arama optimizasyonunun derleyici tarafından uygulandığını sanıyordum. Derleyici tarafından kuyruk çağrısı optimize edilebilecek bir işleve sahip olduğunuzu varsayarsak, aynı işlevi bir döngü kullanarak uygulayan eşdeğer özyinelemeli olmayan bir işleve sahip olabilirsiniz, değil mi? Eğer öyleyse, bu derleyici tarafından yapılamaz. JVM'ye olan bağımlılığı takip edemiyorum. Bu, yerel i386 kodunu oluşturan bir Scheme derleyicisiyle nasıl karşılaştırılır?
Gautham Ganapathy

4
@Gautham: Hata ayıklama hakkındaki açıklamam, JVM'de kuyruk çağrısının ortadan kaldırılmaması için bir geçici çözüm olarak trambolinlerin kullanılmasıyla ilgiliydi. Kuyruk çağrısının ortadan kaldırılması JVM'de uygulanabilir ve uygulanmıştır (Arnold Schaighofer OpenJDK'da yaptı ve ayrıca LLVM), bu nedenle yapılıp yapılamayacağı konusunda hiçbir soru yoktur. Microsoft'un CLR'si, tabii ki, 10 yıldır kuyruk çağrısının ortadan kaldırılmasını destekledi ve F # sürümü, oyunun kurallarını değiştirdiğini gösterdi. Bence yanıt, JVM'nin çoktan durgun olması.
JD

3
Bu yaygın bir yanlış anlama ve sık sık tekrarlanan bir bahanedir, ancak yanlıştır. Yığın incelemesi yoluyla güvenliğin (ve yararlı yığın izlerinin sağlanması) uygun kuyruk aramalarıyla uyumsuz olmadığı birkaç yıldır iyice yerleşmiştir. Örneğin, 2004 bu incelemeye bakın citeseerx.ist.psu.edu/viewdoc/... yanıt yanlış olduğu gibi, Downvoting.
Justin Sheehy

5
@JustinSheehy: Yanlış olan ne? Soru şuydu: "JVM kuyruk arama optimizasyonlarını engelliyor mu?" Ve cevap, "Hayır, ama zor."
Michael Myers

5
java8'de bunun dahil olup olmadığını biliyor musunuz?
nachokk

27

Temel sınırlama basitçe JVM'nin bayt kodunda kuyruk aramaları sağlamaması ve sonuç olarak JVM üzerine inşa edilmiş bir dilin kendi kendine kuyruk aramaları sağlamasının doğrudan bir yolu olmamasıdır. Benzer bir etki (örn. Tramplen) elde edebilen geçici çözümler vardır, ancak bunlar, korkunç bir performansın ve bir hata ayıklayıcıyı işe yaramaz hale getiren üretilen ara kodu gizlemenin ciddi maliyetiyle gelir.

Bu nedenle Sun, JVM'nin kendisinde kuyruk çağrılarını uygulayana kadar JVM, üretim kalitesinde işlevsel programlama dillerini destekleyemez. Bunu yıllardır tartışıyorlar, ancak kuyruk çağrılarını uygulayacaklarından şüpheliyim: bu çok zor olacak çünkü bu tür temel işlevleri uygulamadan önce sanal makinelerini zamanından önce optimize ettiler ve Sun'ın çabası işlevsel diller yerine dinamik dillere odaklanıyor.

Bu nedenle, Scala'nın gerçek bir işlevsel programlama dili olmadığına dair çok güçlü bir argüman var: Bu diller, Scheme'nin 30 yıldan uzun bir süre önce piyasaya sürülmesinden bu yana, kuyruk çağrılarını temel bir özellik olarak görüyorlar.


5
Hence there is a very strong argument that Scala is not a real functional programming language - argüman aslında oldukça zayıf. Tabii ki tail calls [as] an essential feature, temeldeki donanım (veya virtal makine) doğrudan destekliyorsa güzel. Ancak uygulama ayrıntıları.
Ingo

8
@Ingo: Yalnızca programınızda kullanıcı tarafından görülen çalışma zamanında yığın taşmalarını önemli bir sorun olarak görmüyorsanız. Hata izleyicisine göre, Scala derleyicisinin kendisi bile yığın taşmalarıyla boğuşmuştur. Yani en tecrübeli Scala geliştiricileri bile hala yanlış
JD

7
F # 'ın savunucusu olmakta sorun yok. Ama seni uzun zamandır (usenet'te yıllar önce bile) F # olmayan her şeye düşman olduğun için fark ettim, ama yine de detayların, neden bahsettiğini bilmediğini gösteriyor. Burada olduğu gibi: argümanınız, yığın taşmasıyla iptal eden bir program yazabileceğim bir dilin işlevsel bir dil olmadığı gibi görünüyor? Ama yığın taşmasına neden olabileceğim diller için aynı argüman yapılamaz mı? Bu nedenle, kutsal F # 'nin kendisi işlevsel olarak sayılmaz.
Ingo

7
@Ingo: Karşılıklı özyineleme ve sürdürme geçiş stili gibi işlevsel programlamadaki çeşitli deyimler, kuyruk çağrısının ortadan kaldırılmasını gerektirebilir. Onsuz, programlarınız taşar. Bir dil, deyimsel işlevsel kodu güvenilir bir şekilde çalıştıramıyorsa, işlevsel mi? Cevap, sizin de söylediğiniz gibi bir yargı çağrısıdır, ancak pratikte önemli bir ayrımdır. Martin Trojer bununla
JD

2
yine de, sırf JVM'nin (ne yazık ki soru yok) kuyruk aramaları yapamaması, bu, kuyruk aramasının ortadan kaldırılmasının imkansız olduğu anlamına gelmez. Bu, kayan nokta hesaplamalarının yalnızca FPU'lu bilgisayarlarda mümkün olduğu belirtilmiş gibidir.
Ingo

22

Scala 2.7.x, son yöntemlerin ve yerel işlevlerin kendi kendine özyinelemesi (kendini çağıran bir işlev) için kuyruk arama optimizasyonunu destekler.

Scala 2.8, karşılıklı olarak özyinelemeli işlevleri optimize etmek için bir teknik olan trambolin için kütüphane desteğiyle de gelebilir.

Rich Dougherty'nin blogunda Scala özyinelemesinin durumu hakkında pek çok bilgi bulunabilir .


Lütfen mevcut ölçek durumu hakkındaki soruyu günceller misiniz?
om-nom-nom

@ om-nom-nom AFAIK, ne Scala tarafında ne de JVM tarafında hiçbir şey değişmedi.
Daniel C. Sobral


0

Tüm kaynaklar , JVM'nin kuyruk özyineleme durumunda optimize edemediğine işaret ediyor, ancak Java performans ayarını (2003, O'reilly) okuduktan sonra yazarı, kuyruk özyinelemeyi uygulayarak daha yüksek özyineleme performansı elde edebileceğini iddia eden buldum.

İddiasını 212. sayfada bulabilirsiniz ('kuyruk özyineleme' için arama ikinci sonuç olmalıdır). Ne oluyor?


IBM, JVM uygulamasında bir tür TCO'yu desteklemiştir (bir optimizasyon olarak, dolayısıyla garanti yoktur). Belki de Java Performans ayarının yazarları bu özelliğin sonunda tüm JVM'ler tarafından uygulanacağını düşündüler. ibm.com/developerworks/java/library/j-diag8.html
llemieng
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.