JVM이 테일 호출 최적화를 방지합니까?


99

다음 질문에 대한 인용문을 보았습니다 . 웹 서비스를 구축 할 좋은 기능적 언어는 무엇입니까?

특히 Scala는 수행 할 수있는 구성의 종류를 제한하는 자체 재귀 함수를 제외하고는 꼬리 호출 제거를 지원하지 않습니다 (이는 JVM의 근본적인 제한 사항입니다).

이것이 사실입니까? 그렇다면 이러한 근본적인 한계를 만드는 JVM은 무엇입니까?

답변:


74

이 게시물 : 재귀 또는 반복? 도움이 될 수 있습니다.

간단히 말해서, 보안 모델과 항상 스택 추적을 사용할 수 있어야하기 때문에 테일 호출 최적화는 JVM에서 수행하기 어렵습니다. 이론상 이러한 요구 사항은 지원 될 수 있지만 아마도 새로운 바이트 코드가 필요할 것입니다 ( John Rose의 비공식적 제안 참조 ).

평가 (2002 년부터)가 끝나는 썬 버그 # 4726340 에서 더 많은 논의가 있습니다 .

그래도 할 수 있다고 생각하지만 작은 일이 아닙니다.

현재 Da Vinci Machine 프로젝트 에서 몇 가지 작업이 진행되고 있습니다. 테일 콜 하위 프로젝트의 상태는 "proto 80 %"로 나열됩니다. Java 7로 만들 가능성은 낮지 만 Java 8에서는 매우 좋은 기회가 있다고 생각합니다.


나는 설명을 잘 따르지 않았습니다. 테일 호출 최적화가 컴파일러에 의해 구현되었다고 생각했습니다. 컴파일러에 의해 마무리 호출이 최적화 될 수있는 함수가 있다고 가정하면 루프를 사용하여 동일한 기능을 구현하는 동등한 비 재귀 함수도 가질 수 있습니다. 맞습니까? 그렇다면 컴파일러에서이 작업을 수행 할 수 없습니다. JVM에 대한 의존성을 따를 수 없습니다. 네이티브 i386 코드를 생성 한 Scheme 컴파일러와 비교하면 어떻습니까?
Gautham Ganapathy

4
@Gautham : 디버깅에 대한 제 진술은 JVM에서 꼬리 호출 제거가 부족한 문제를 해결하기 위해 트램폴린을 사용하는 것과 관련이 있습니다. 테일 콜 제거는 JVM (Arnold Schaighofer가 OpenJDK 및 LLVM에서 수행함)에서 구현 될 수 있으며 구현되었으므로 수행 할 수 있는지 여부에 대해서는 의문의 여지가 없습니다. 물론 Microsoft의 CLR은 10 년 동안 테일 콜 제거를 지원했으며 F #의 출시는 이것이 게임 체인저임을 입증했습니다. 대답은 JVM이 정체 된 지 오래되었다는 것입니다.
JD

3
이것은 일반적인 오해이자 자주 반복되는 변명이지만 잘못된 것입니다. 스택 검사 (및 유용한 스택 추적 제공)에 의한 보안이 적절한 테일 호출과 호환되지 않는다는 것은 수년 동안 잘 알려져 있습니다. 예를 들어 2004 년의이 문서를 참조하십시오. citeseerx.ist.psu.edu/viewdoc/… 대답이 틀 렸기 때문에 반대 투표.
Justin Sheehy

5
@JustinSheehy : 무엇이 잘못 되었나요? 질문은 "JVM이 테일 호출 최적화를 방지합니까?"였습니다. 대답은 "아니요.하지만 어렵습니다."
Michael Myers

5
java8에 이것이 포함되어 있는지 알고 있습니까?
nachokk 2014

27

근본적인 제한은 단순히 JVM이 바이트 코드에서 테일 호출을 제공하지 않기 때문에 JVM에 빌드 된 언어가 자체적으로 테일 호출을 제공하는 직접적인 방법이 없다는 것입니다. 유사한 효과 (예 : 트램폴린)를 달성 할 수있는 해결 방법이 있지만 끔찍한 성능과 생성 된 중간 코드를 난독 화하여 디버거를 쓸모 없게 만드는 엄청난 비용이 발생합니다.

따라서 JVM은 Sun이 JVM 자체에서 테일 호출을 구현할 때까지 생산 품질의 함수형 프로그래밍 언어를 지원할 수 없습니다. 그들은 수년 동안 그것에 대해 논의 해 왔지만 그들이 테일 콜을 구현할 것 같지 않습니다. 이러한 기본 기능을 구현하기 전에 VM을 조기에 최적화했기 때문에 매우 어려울 것이며 Sun의 노력은 기능적 언어가 아닌 동적 언어에 집중되어 있습니다.

따라서 Scala가 실제 함수형 프로그래밍 언어가 아니라는 매우 강력한 주장이 있습니다. 이러한 언어는 30 년 전에 Scheme이 처음 소개 된 이후 테일 호출을 필수 기능으로 간주했습니다.


5
Hence there is a very strong argument that Scala is not a real functional programming language -논쟁은 실제로 매우 약합니다. 물론 tail calls [as] an essential feature기본 하드웨어 (또는 가상 머신)가이를 직접 지원한다면 좋습니다. 그러나 구현 세부 사항입니다.
Ingo

8
@Ingo : 런타임에 프로그램의 스택 오버플로가 사용자에게 심각한 문제라고 생각하지 않는 경우에만 가능합니다. 버그 추적기에 따르면 Scala 컴파일러 자체조차도 스택 오버플로로 시달리고 있습니다. 따라서 가장 노련한 Scala 개발자조차도 여전히 잘못 알고 있습니다 ...
JD

7
F #의 옹호자가 되어도 괜찮습니다. 그러나 나는 F #이 아닌 모든 것에 적대적이라는 이유로 오랫동안 (유즈넷에서 심지어 몇 년 전에) 언급했지만, 당신의 정교함은 당신이 무슨 말을하는지 모른다는 것을 보여줍니다. 여기와 같이 : 귀하의 주장은 스택 오버플로로 중단되는 프로그램을 작성할 수있는 언어가 기능적인 언어가 아니라는 것 같습니다. 그러나 힙 오버플로를 유발할 수있는 언어에 대해 동일한 주장을 할 수 없습니까? 따라서 거룩한 F # 자체는 기능적으로 간주되지 않습니다.
Ingo 2011

7
@Ingo : 상호 재귀 및 연속 전달 스타일과 같은 함수형 프로그래밍의 여러 관용구가 작동하려면 꼬리 호출 제거가 필요할 수 있습니다. 그것 없이는 프로그램이 스택 오버플로됩니다. 언어가 관용적 기능 코드를 안정적으로 실행할 수없는 경우 작동합니까? 대답은 당신이 말했듯이 판단 호출이지만 실제로는 중요한 차이입니다. Martin Trojer는 이에 대한 흥미로운 블로그 게시물을 게시했습니다. martinsprogrammingblog.blogspot.com/2011/11/…
JD

2
그럼에도 불구하고 JVM (아쉽게도 의심의 여지가 없음)이 테일 콜을 수행 할 수 없다고해서 테일 콜 제거가 불가능하다는 의미는 아닙니다. 이것은 부동 소수점 계산이 FPU가있는 컴퓨터에서만 가능하다고 언급 한 것과 같습니다.
Ingo 2011

22

Scala 2.7.x는 최종 메서드 및 로컬 함수의 자체 재귀 (자신을 호출하는 함수)에 대한 테일 호출 최적화를 지원합니다.

Scala 2.8에는 상호 재귀 함수를 최적화하는 기술인 트램폴린에 대한 라이브러리 지원도 함께 제공 될 수 있습니다.

Scala 재귀 상태에 대한 많은 정보는 Rich Dougherty의 블로그 에서 찾을 수 있습니다 .


현재 스칼라 상태에 대한 질문을 업데이트 해 주시겠습니까?
om-nom-nom 2013

@ om-nom-nom AFAIK, Scala 쪽이나 JVM 쪽에서 아무것도 변경되지 않았습니다.
Daniel C. Sobral 2013-04-12


0

모든 소스는 JVM이 꼬리 재귀의 경우 최적화 할 수 없다고 지적하지만 Java 성능 튜닝 (2003, O'reilly)을 읽은 후 저자는 꼬리 재귀를 구현하여 더 큰 재귀 성능을 달성 할 수 있다고 주장했습니다.

그의 주장은 212 페이지에서 찾을 수 있습니다 ( '꼬리 재귀'를 검색하면 두 번째 결과가됩니다). 무엇을 제공합니까?


IBM은 JVM 구현에서 특정 형태의 TCO를 지원했습니다 (최적화로 보장되지 않음). Java 성능 조정 작성자는이 기능이 결국 모든 JVM에서 구현 될 것이라고 생각했을 것입니다. ibm.com/developerworks/java/library/j-diag8.html
llemieng
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.