시험 적으로 비싸다


14

함수를 종료하기 전에 리소스 정리를 수행해야하는 코드의 경우이 두 가지 방법간에 성능 차이가 크게 있습니다.

  1. 모든 반품 진술 전에 자원 청소

    void func()
    {
        login();
    
        bool ret = dosomething();
        if(ret == false)
        {
            logout();
            return;
        }
    
        ret = dosomethingelse();
        if(ret == false)
        {
            logout();
            return;
        }
    
        dootherstuff();
    
        logout();
    }
  2. finally 블록에서 리소스 정리

    void func()
    {
        login();
    
        try
        {
            bool ret = dosomething();
            if(ret == false)
                return;
    
            ret = dosomethingelse();
            if(ret == false)
                return;
    
            dootherstuff();
    
        }
        finally
        {
            logout();
        }
    }

샘플 프로그램에서 몇 가지 기본 테스트를 수행했지만 큰 차이는 없습니다. 나는 finally이것을 하는 방법을 훨씬 선호 하지만 큰 프로젝트에서 성능이 저하되는지 궁금합니다.


3
실제로 답변으로 게시 할 가치는 없지만 아닙니다. 예외를 기본 오류 처리 전략으로 예상하는 Java를 사용하는 경우 try / catch / finally를 사용해야합니다. 언어는 사용중인 패턴에 맞게 최적화됩니다.
Jonathan Rich

1
@JonathanRich : 어떻게?
haylem

2
달성하려는 것을 표현하는 방식으로 코드를 깨끗하게 작성하십시오. 나중에 문제가 있다는 것을 알게되면 나중에 최적화 하십시오. 처음에는 느리지 않은 무언가를 몇 밀리 초 정도 줄일 수 있다고 생각하기 때문에 언어 기능을 사용하지 마십시오.
Sean McSomething

@mikeTheLiar-당신이 내가 써야한다는 것을 의미한다면 if(!cond), 이것이 나를 자바로 만든 것입니다. C ++에서는 부울 코드와 다른 유형의 코드를 작성하는 방법 int x; if(!x)입니다. java는 이것을 위해서만 이것을 사용할 수 있기 때문에 java booleans에서 if(cond)& if(!cond)를 사용하는 것을 완전히 중단 했습니다.
user93353

1
저를 슬프게하는 @ user93353. (someIntValue != 0)부울을 평가하는 것보다 비교하는 것보다 훨씬 볼 것입니다. 그것은 나에게 냄새가 나고, 나는 야생에서 그것을 볼 때 즉시 그것을 리팩터링합니다.
MikeTheLiar

답변:


23

에 나타난 바와 같이 얼마나 느린 자바 예외? 속도 저하가 try {} catch {}예외 자체의 영향을 받는다는 것을 알 수 있습니다.

예외를 만들면 런타임에서 전체 호출 스택을 가져오고 비용이 발생합니다. 당신이 예외를 생성하지 않는 경우이 아니라 아주 약간의 시간의 증가.

이 질문에 주어진 예에서 예외는 없으며 예외가 발생하지 않을 것으로 예상됩니다. 대신에, try {} finally {}finally 블록 내에서 리소스 할당 해제를 처리 하는 방법 이 있습니다.

따라서 질문에 대답하기 try {} finally {}위해 예외를 사용하지 않는 구조 내에서 실제 런타임 비용 은 없습니다 (보지 않은 것처럼 들리지 않습니다). 무엇 이며 하나의 코드를 읽고이 전형적인 코드가 아닌 스타일을보고 코더 다른 뭔가 후이 방법에서 일어나는 것을 주위에 그들의 마음을 얻을 수있을 때 가능 비용은 유지 보수 시간 return이전 호출에 반환하기 전에.


앞에서 언급했듯이 유지 관리는 이 작업을 수행하는 가지 방법 모두에 대한 논쟁입니다 . 기록을 위해, 고려 후에, 나의 선호는 최종 접근 방식이 될 것입니다.

누군가에게 새로운 언어 구조를 가르치는 유지 관리 시간을 고려하십시오. 보는 것은 try {} finally {}종종 Java 코드에서 볼 수있는 것이 아니므로 사람들에게 혼란을 줄 수 있습니다. 사람들이보기에 익숙한 것보다 Java에서 조금 더 고급 구조를 학습하는 데 약간의 유지 보수 시간이 있습니다.

finally {}블록은 항상 실행됩니다. 그리고 이것이 당신이 그것을 사용해야하는 이유입니다. 누군가가 적절한 시간에 로그 아웃을 포함하는 것을 잊어 버렸거나 부적절한 시간에 호출하거나 두 번 호출되도록 호출 한 후 리턴 / 종료하는 것을 잊었을 때 비 최종 접근법을 디버깅하는 유지 보수 시간도 고려하십시오. 이것의 사용 가능한 버그가 너무 많아서 사용할 try {} finally {}수 없습니다.

이 두 가지 비용을 측정 할 때는 접근 방식 을 사용 하지 않는 유지 관리 시간이 비쌉니다 try {} finally {}. 사람들은 try {} finally {}블록이 다른 버전과 비교할 때 몇 밀리 초 또는 추가 jvm 명령에 대해 알 수 있지만 리소스 할당 해제를 해결하는 이상적인 방법보다 디버깅에 소요되는 시간도 고려해야합니다.

유지 관리 가능한 코드를 먼저 작성하고 나중에 버그가 작성되는 것을 방지하는 방식으로 작성하십시오.


1
"제안 / 마지막으로 런타임 예외와 관련하여 보장하지 않는 보증을 제공합니다. 원하든 원하지 않든 모든 라인은 사실상 예외를 던질 수 있습니다."-Me : 정확히 맞지는 않습니다. . 질문에 주어진 구조 에는 코드 성능을 저하시키는 추가 예외 가 없습니다 . 비시도 / 완료 블록과 비교하여 시도 / 마지막으로 블록을 감싸서 추가적인 성능 영향 은 없습니다 .

2
시험 사용의 최종 사용을 이해하는 것보다 유지 관리에 더 많은 비용이 드는 것은 몇 가지 정리 블록을 유지해야합니다. 적어도 추가 청소가 필요한 경우 한곳 만 두어야한다는 것을 알고 있습니다.
Bart van Ingen Schenau

트윗 담아 가기 try-finally는 아마도 그것을 처리하는 가장 좋은 방법 일 것입니다. 코드에서 본 일반적인 구조는 아닙니다. 사람들은 마침내 catch catch와 예외 처리를 이해하려고 시도하는 데 어려움이 있습니다. -잡기없는 파이널? 뭐? 사람들은 정말로 그것을 이해하지 못한다 . 제안한대로 언어 구조를 피하고 잘못 수행하는 것보다 언어 구조를 이해하는 것이 좋습니다.

나는 주로 시험 최종 대안이 무료가 아니라는 것을 알고 싶었습니다. 비용에 대한 귀하의 추가 사항에 대해 다른 의견을 제시 할 수 있기를 바랍니다.
Bart van Ingen Schenau

5

/programming/299068/how-slow-are-java-exceptions

이 질문에 대한 답변은 try catch 블록 비용으로 함수 호출을 랩핑하여 베어 함수 호출보다 5 % 미만임을 보여줍니다. 실제로 예외를 던지고 잡으면 런타임이 베어 함수 호출의 66 배 이상으로 벌어졌습니다. 따라서 예외 디자인이 정기적으로 발생하는 것으로 예상되면 (정확하게 프로파일 링 된 성능 결정 코드에서) 예외를 피하려고 시도하지만 예외적 인 상황이 드문 경우 큰 문제는 아닙니다.


3
"뛰어난 상황이 드물다면" -거기에 팽팽한 설명이 있습니다. 예외적이라는 것은 드문 의미이며 예외를 사용해야하는 방식입니다. 설계 또는 제어 흐름의 일부가되어서는 안됩니다.
Jesse C. Slicer

1
실제로 예외는 드문 일이 아니며 우연한 부작용 일뿐입니다. 예를 들어 UI가 나쁜 사람은 일반적인 흐름보다 예외 사용 사례 흐름이 더 자주 발생할 수 있습니다.
Esailija

2
질문 코드에 예외가 발생하지 않습니다.

2
@ JesseC.Slicer 흐름 제어로 사용되는 언어가 드문 경우가 있습니다. 예를 들어 파이썬에서 무언가를 반복 할 때 반복자는 완료되면 중지 예외를 throw합니다. 또한 OCaml에서 표준 라이브러리는 "행복하게 던져지는"것처럼 보이며, 드물지 않은 많은 상황에서 발생합니다 (지도가 있고 맵에 존재하지 않는 것을 찾으려고하면 ).
stonemetal

@stonemetal PythonError와 마찬가지로 KeyError와 함께
Izkata

4

최적화하는 대신 코드가하는 일을 생각하십시오.

finally 블록을 추가하는 것은 다른 구현입니다. 즉, 모든 예외에서 로그 아웃됩니다.

특히-로그인에서 예외가 발생하면 두 번째 함수의 동작이 첫 번째 동작과 다릅니다.

로그인과 로그 아웃이 실제로 함수 동작의 일부가 아닌 경우 메소드가 한 가지 일만 잘 수행해야한다고 제안합니다.

    void func()
    {
            bool ret = dosomething();
            if(ret == false)
                return;

            ret = dosomethingelse();
            if(ret == false)
                return;

            dootherstuff();

    }

로그인 / 로그 아웃을 관리하는 컨텍스트에 이미 캡슐화 된 기능에 있어야합니다. 기본 코드와 기본적으로 다르게 보입니다.

귀하의 게시물은 Java로 태그되어 있지만 익숙하지 않지만 .net에서는 using 블록을 사용합니다.

즉 :

    using(var loginContext = CreateLoginContext()) 
    {
            // Do all your stuff
    }

그리고 로그인 컨텍스트에는 자원을 로그 아웃하고 정리하는 Dispose 메소드가 있습니다.

편집 : 나는 실제로 질문에 대답하지 않았습니다!

나는 측정 가능한 증거가 없지만 이것이 조기 최적화에 합당하기에 더 비싸거나 확실히 비싸지 않을 것으로 예상합니다.

질문에 대답하지는 않지만 OP에 도움이된다고 생각하기 때문에 나머지 답변을 남겨 두겠습니다.


1
답변을 완성하기 위해 Java 7 using은 문제의 리소스가 AutoCloseable인터페이스를 구현한다고 가정하고 .net 구문 과 유사한 try-with-resources 문을 도입했습니다 .
haylem

ret변수를 제거하고 한 줄 후에 한 번만 검사하도록 두 번 할당했습니다. 확인하십시오 if (dosomething() == false) return;.
ott--

동의했지만 OP 코드를 제공된 방식으로 유지하고 싶었습니다.
Michael

@ ott-- OP의 코드가 유스 케이스를 단순화 한 것으로 가정합니다. 예를 들어, 더 유사한 것이있을 수 ret2 = doSomethingElse(ret1)있지만 질문과 관련이 없으므로 제거되었습니다.
Izkata

if (dosomething() == false) ...나쁜 코드입니다. 좀 더 직관적으로 사용if (!dosomething()) ...
Steffen Heil

1

가정 : C # 코드로 개발 중입니다.

빠른 답변은 try / finally 블록을 사용하여 성능이 크게 저하되지 않는다는 것입니다. 예외를 던지고 잡을 때 성능이 저하됩니다.

더 긴 대답은 당신 자신을 보는 것입니다. 생성 된 기본 CIL 코드 ( 예 : 레드 게이트 리플렉터) 를 보면 생성 된 기본 CIL 명령어를보고 그 영향을 확인할 수 있습니다.


11
질문은 java 태그가 붙어 있습니다.
Joachim Sauer

잘 발견되었습니다! ;)
Michael Shaw

3
또한 대문자로 표시되지 않은 방법이지만 맛이 좋을 수도 있습니다.
Erik Reppen

c # :) 질문 인 경우에도 여전히 좋은 대답
PhillyNJ

-2

다른 사람들이 이미 언급했듯이 Ttese 코드는 예외가 발생 dosomethingelse하거나 dootherstuff예외가 발생 하면 결과가 다릅니다 .

그리고 예, 모든 함수 호출은 적어도 StackOVerflowError! 이들을 올바르게 처리하는 것은 드물게 가능하지만 (예를 들어 모든 클린업 기능은 동일한 문제가있을 수 있으므로, 예를 들어 잠금 구현과 같은) 경우에 따라 올바르게 처리하는 것이 중요합니다 ...


2
이것은 이전의 6 가지 답변보다 실질적인 것을 제공하지 않는 것 같습니다
gnat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.