자바 메소드 호출 비용


82

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

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 개의 메서드 호출을 수행하면 어떻게됩니까? 최고의 프로그래밍 방법은 무엇입니까?


4
하지만 지금 메서드를 호출하면 SECOND 메서드 호출이 발생합니다. 완전 무료입니다! 배송 및 취급 비용 만 지불하십시오! 심각하게 생각. 더 많은 코드를로드해야하는 오버 헤드와 마찬가지로 메서드 호출에도 오버 헤드가 있습니다. 어느 시점에서 하나는 다른 것보다 더 비싸집니다. 알 수있는 유일한 방법은 코드를 벤치마킹하는 것입니다.
Marc B

11
3 ... 2 ... 1에서 조기 최적화 따옴표

22
나는 이것에 대해 반대표를 던지는 이유를 알지 못합니다. 그 사람은 완벽하게 합법적 인 질문을하고 있습니다. 어떤 사람들에게는 분명한 대답 일 수 있지만 그렇다고 나쁜 질문이되는 것은 아닙니다!
Michael Berry

3
사실, 이것은 매우 합법적 인 질문이며, 정확한 중복이있는 경우에만 반대표의 이유가 될 수 있습니다.
Arafangion 2011-06-27

1
분명하다면 미안하지만 혼자 배우고 있고 몇 달 밖에되지 않았습니다. 온라인 샘플 코드에서 본 것 중 일부는 좋은 습관이 아닌 것으로 나타 났으므로 다시 확인하고 싶습니다.
jhlu87 2011-06-27

답변:


74

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

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

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

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

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

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

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

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


벤치마킹하는 좋은 방법은 무엇입니까? 다운로드 할 수있는 소프트웨어가 있습니까? 아니면 시작과 끝에서 System.nanoTime ()을 사용하고 차이점을 인쇄한다는 의미입니까?
jhlu87 2011-06-27

System.nanoTime()또는 System.currentTimeMillis프로파일 링을 수행하는 잘못된 방법입니다. 이 Stackoverflow 질문 의 답변에서 프로파일 러 목록을 얻을 수 있습니다 . 지금은 JDK와 함께 제공되므로 VisualVM을 권장합니다.
Vineet Reynolds 2011-06-27

2
@ jhlu87 : 메서드 호출의 오버 헤드를 정확하게 추정하는 것이 매우 어렵다고 생각합니다. Microbenchmarking은 제대로하기가 매우 어려우며 일반적으로 대대적 인 계획에는 그다지 유용하지 않습니다. 이것을 읽으십시오 .
ColinD 2011 년

@VineetReynolds 연결된 질문이 죽었습니다.
dim8

19

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

성능 관점 에서 메서드를 인라인 할 이유가 없습니다 . 성능 문제인 경우 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에서는 원하는 모든 메서드 호출을 수행해야합니다.


1
메소드 호출 비싼인지 아닌지 나는 그가 스타일의 코딩 팁이 아니라 알고 요구했다 생각하지 않는다
Asaf Mesika

3
그는 "최고의 프로그래밍 방법은 무엇입니까?"라고 명시 적으로 물었습니다. -모범 사례로서 이것은 완벽하게 관련이 있습니다.
Daniel Martin

2
마지막 문장 만 취하면이 질문의 맥락을 완전히 잃게됩니다. 그는 큰 메서드를 여러 개의 작은 메서드로 나누는 데 비용이 많이 드는지 알고 싶어합니다. 메서드 호출에는 가격이 있기 때문입니다. 생성자에서 최종이 아닌 메서드를 호출하는 안티 패턴을 설명하는 답변을 추가하는 것은 전체 질문에 대한 답변으로 간주되지 않습니다. 아, 그리고 "메소드 호출이 얼마나 비싼"질문의 제목 체크 아웃
Asaf Mesika

6

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


4

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

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

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

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


3

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

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

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


3

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


1

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

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

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


이러한 질문을하지 않고 이미 자체 방법에 코드를 넣는 것이 더 쉽습니다!
Arafangion 2011-06-27

2
질문자는 자신의 메서드 호출의 세분화가 무엇인지 궁금합니다. 그냥 사용할 수 있다면 정수를 증가시키는 메서드를 만들 필요가 없습니다i++;
Peaches491

실제로 재사용 할 기회가 없더라도 메서드를 만드는 데는 많은 가치가 있습니다. 코드 블록에 이름을 지정하고 전체 구조를 표시하는 것만으로도 큰 이점이 있습니다.
Joffrey

1

clear()가독성에 도움이 될 때 방법을 유지하십시오 . 유지 관리 할 수없는 코드는 더 비쌉니다.


1

컴파일러를 최적화하면 일반적으로 이러한 "추가"작업에서 중복성을 제거 할 수 있습니다. 많은 경우에 "최적화 된"코드와 단순히 원하는 방식으로 작성된 코드와 최적화 컴파일러를 통해 실행되는 코드 간의 차이는 없습니다. 즉, 최적화 컴파일러는 일반적으로 사용자가하는 것처럼 좋은 작업을 수행하며 소스 코드를 저하시키지 않고 수행합니다. 실제로 컴파일러는 최적화를 수행 할 때 많은 것을 고려하기 때문에 "수작업으로 최적화 된"코드는 효율성이 떨어집니다. 코드를 읽을 수있는 형식으로 남겨두고 나중에 최적화에 대해 걱정하지 마십시오.

"조기 최적화는 모든 악의 근원입니다." -도널드 크 누스


0

메서드 호출에 대해서는 그다지 걱정하지 않지만 메서드의 논리는 걱정하지 않습니다. 중요한 시스템이고 시스템이 "빠르다"면 실행하는 데 오래 걸리는 코드를 최적화하는 방법을 살펴볼 것입니다.


0

현대 컴퓨터의 메모리를 감안할 때 이것은 매우 저렴합니다. 누군가가 무슨 일이 일어나고 있는지 빨리 읽을 수 있도록 코드를 메소드로 나누는 것이 항상 좋습니다. 오류가 몇 줄의 본문이있는 단일 메서드로 제한되는 경우 코드의 오류 범위를 좁히는데도 도움이됩니다.


0

다른 사람들이 말했듯이, 컴파일러가이를 최적화하기 때문에 메서드 호출 비용은 사소한 수준입니다.

즉, 생성자에서 인스턴스 메서드에 대한 메서드 호출을 수행하는 데는 위험이 있습니다. 생성자에 의해 아직 시작되지 않은 인스턴스 변수를 사용하려고 시도 할 수 있도록 나중에 인스턴스 메서드를 업데이트 할 위험이 있습니다. 즉, 생성자에서 생성 활동을 분리 할 필요는 없습니다.

또 다른 질문은 clear () 메서드가 루트를 EMPTY로 설정하여 객체가 생성 될 때 초기화된다는 것입니다. 그런 다음 EMPTY에 노드를 추가하고 clear ()를 호출하면 루트 노드를 재설정하지 않습니다. 이것이 당신이 원하는 행동입니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.