[java] 자바 메소드 호출 비용

나는 초보자이고 코드를 반복하는 것이 나쁘다는 것을 항상 읽었습니다. 그러나 그렇게하지 않으려면 일반적으로 추가 메서드 호출이 필요합니다. 다음 수업이 있다고 가정 해 봅시다.

public class BinarySearchTree<E extends Comparable<E>>{
    private BinaryTree<E> root;
    private final BinaryTree<E> EMPTY = new BinaryTree<E>();
    private int count;
    private Comparator<E> ordering;

    public BinarySearchTree(Comparator<E> order){
        ordering = order;
        clear();
    }

    public void clear(){
        root = EMPTY;
        count = 0;
    }
}

실제 메서드를 호출하는 대신 clear () 메서드의 두 줄을 생성자에 복사하여 붙여 넣는 것이 더 최적일까요? 그렇다면 얼마나 많은 차이가 있습니까? 생성자가 각각 인스턴스 변수를 값으로 설정하여 10 개의 메서드 호출을 수행하면 어떻게됩니까? 최고의 프로그래밍 방법은 무엇입니까?



답변

실제 메서드를 호출하는 대신 clear () 메서드의 두 줄을 생성자에 복사하여 붙여 넣는 것이 더 최적일까요?

컴파일러는 이러한 최적화를 수행 할 수 있습니다. JVM도 마찬가지입니다. 컴파일러 작성자 및 JVM 작성자가 사용하는 용어는 “인라인 확장”입니다.

그렇다면 얼마나 많은 차이가 있습니까?

그것을 측정하십시오. 종종 차이가 없다는 것을 알게 될 것입니다. 그리고 이것이 성능 핫스팟이라고 생각한다면 잘못된 위치를 찾고있는 것입니다. 그것이 당신이 그것을 측정해야하는 이유입니다.

생성자가 각각 인스턴스 변수를 값으로 설정하여 10 개의 메서드 호출을 수행하면 어떻게됩니까?

다시 말하지만 이는 생성 된 바이트 코드와 Java Virtual Machine에서 수행하는 런타임 최적화에 따라 다릅니다. 컴파일러 / JVM이 메서드 호출을 인라인 할 수있는 경우 런타임에 새 스택 프레임을 만드는 오버 헤드를 방지하기 위해 최적화를 수행합니다.

최고의 프로그래밍 방법은 무엇입니까?

조기 최적화 방지. 가장 좋은 방법은 읽기 쉽고 잘 설계된 코드를 작성한 다음 애플리케이션의 성능 핫스팟에 맞게 최적화하는 것입니다.


답변

최적화에 대해 다른 사람들이 말한 것은 절대적으로 사실입니다.

성능 관점 에서 메서드를 인라인 할 이유가 없습니다 . 성능 문제인 경우 JVM의 JIT가이를 인라인합니다. 자바에서 메서드 호출은 무료에 가깝기 때문에 생각할 가치가 없습니다.

즉, 여기에는 다른 문제가 있습니다. 즉, 그것은 이다 덮어 쓸 방법 (즉, 아닌 하나의 전화 나쁜 프로그래밍 연습 final, static또는 private생성자에서이). (Effective Java, 2nd Ed., p. 89 항목의 “상속을위한 설계 및 문서 또는 기타 금지”항목)

누군가 다음 과 같은 코드로 모든 공용 메서드를 재정의하는 BinarySearchTreecalled 하위 클래스를 추가하면 어떻게 되나요?LoggingBinarySearchTree

public void clear(){
  this.callLog.addCall("clear");
  super.clear();
}

그러면 LoggingBinarySearchTree결코 건설 할 수 없습니다! 문제는이 this.callLog될 것입니다 nullBinarySearchTree생성자가 실행되지만 clear불려 가도록는 오버라이드 (override)이며, 당신이를 얻을 수 있습니다 NullPointerException.

여기서 Java와 C ++가 다릅니다. C ++에서 virtual메서드 를 호출하는 슈퍼 클래스 생성자는 결국 재정의 된 것이 아니라 슈퍼 클래스에 정의 된 생성자를 호출합니다 . 두 언어를 전환하는 사람들은 때때로 이것을 잊어 버립니다.

이를 감안할 때 생성자에서 호출 될 때clear 메서드 를 인라인하는 것이 귀하의 경우 더 깨끗하다고 ​​생각 하지만 일반적으로 Java에서는 원하는 모든 메서드 호출을 수행해야합니다.


답변

나는 그것을 그대로 두겠다. clear()논리 를 변경하면 어떨까요? 두 줄의 코드를 복사 한 모든 위치를 찾는 것은 비현실적입니다.


답변

일반적으로 (그리고 초보자로서 이것은 항상 의미합니다!) 당신이 고려하고있는 것과 같은 마이크로 최적화를해서는 안됩니다. 항상 이와 같은 것보다 코드의 가독성을 선호하십시오.

왜? 컴파일러 / 핫스팟이 이러한 종류의 최적화를 즉시 수행 할 수 있기 때문입니다. 만약 당신이 이런 종류의 라인을 따라 최적화를 시도 할 때 (이 경우는 아니지만) 아마 일을 느리게 만들 것입니다. 핫스팟은 일반적인 프로그래밍 관용구를 이해합니다. 만약 여러분이 직접 최적화를 시도한다면 아마도 여러분이하려는 것을 이해하지 못할 것이고 최적화 할 수 없을 것입니다.

또한 훨씬 더 많은 유지 관리 비용이 있습니다. 코드를 반복하기 시작하면 유지 관리에 훨씬 더 많은 노력이들 것이며, 생각보다 훨씬 더 번거로울 것입니다!

제쳐두고, 코딩 생활에서 낮은 수준의 최적화가 필요한 몇 가지 지점에 도달 할 수 있습니다.하지만 이러한 지점에 도달하면 언제가 왔는지 확실히 알 수 있습니다. 그렇지 않은 경우 언제든지 돌아가서 필요에 따라 나중에 최적화 할 수 있습니다.


답변

가장 좋은 방법은 두 번 측정하고 한 번 자르는 것입니다.

시간 최적화를 낭비한 후에는 다시는 되 찾을 수 없습니다! (따라서 먼저 측정하고 최적화 할 가치가 있는지 자문 해보십시오. 실제 시간을 얼마나 절약 할 수 있습니까?)

이 경우 Java VM은 이미 사용자가 말하는 최적화를 수행하고있을 것입니다.


답변

메서드 호출 의 비용 은 스택 프레임의 생성 (및 폐기)과 메서드에 값을 전달해야하는 경우 추가 바이트 코드 식입니다.


답변

내가 따르는 패턴은 문제의이 방법이 다음 중 하나를 충족하는지 여부입니다.

  • 이 방법을이 수업 밖에서 사용할 수 있으면 도움이 될까요?
  • 이 방법을 다른 방법에서 사용할 수 있으면 도움이됩니까?
  • 필요할 때마다 다시 작성하면 답답할까요?
  • 몇 가지 매개 변수를 사용하여 방법의 다양성을 높일 수 있습니까?

위의 내용 중 하나라도 참이면 자체 메서드로 래핑해야합니다.