0Pricing
Java Academy · 강의

죽은 코드 제거 방지

Blackhole과 상태를 알아봅니다

죽은 코드 제거 방지은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

죽은 코드 제거 방지

마이크로벤치마크에서 가장 큰 함정은 죽은 코드 제거(DCE)입니다. JIT가 결과가 사용되지 않는다고 증명하면 계산을 삭제합니다. 그러면 벤치마크는 아무것도 측정하지 않게 됩니다. JMH는 이를 방지하기 위해 값 반환과 Blackhole이라는 두 가지 도구를 제공합니다.

DCE 함정

이 반복문은 제곱근을 백만 번 계산하지만 결과를 전혀 사용하지 않습니다. 똑똑한 컴파일러는 반복문 전체를 삭제할 수 있습니다.

public class Main {
    public static void main(String[] args) {
        long t = System.nanoTime();
        for (int i = 0; i < 1_000_000; i++) {
            double ignored = Math.sqrt(i); // result thrown away
        }
        System.out.println("ns: " + (System.nanoTime() - t));
    }
}

해결 방법 1: 결과 반환

가장 쉬운 방어 방법은 @Benchmark 메서드에서 계산한 값을 반환하는 것입니다. JMH는 반환된 모든 값을 소비하므로 JVM은 해당 값이 사용되지 않는다고 증명할 수 없습니다.

import org.openjdk.jmh.annotations.Benchmark;

public class Bench {
    @Benchmark
    public double sqrt() {
        return Math.sqrt(42.0); // returned -> consumed by JMH
    }
}

해결 방법 2: 블랙홀

벤치마크가 여러 값을 생성하거나 하나의 값을 반환할 수 없다면 Blackhole을 주입하고 consume(...)을 호출하세요. 블랙홀은 실제 작업을 수행하는 비용 없이 각 값이 사용된다고 JIT를 설득합니다.

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;

public class Bench {
    @Benchmark
    public void manyValues(Blackhole bh) {
        for (int i = 0; i < 100; i++) {
            bh.consume(Math.sqrt(i));
        }
    }
}

@State 객체

@State 클래스는 최적화기가 알 수 없는 입력을 보유하여 상수 접기를 방지합니다. JMH가 이 클래스를 인스턴스화한 뒤 벤치마크에 전달합니다. 범위는 Thread, Benchmark(공유) 또는 Group일 수 있습니다.

import org.openjdk.jmh.annotations.*;

public class Bench {
    @State(Scope.Thread)
    public static class Data {
        public int x = 21;
    }

    @Benchmark
    public int multiply(Data d) {
        return d.x * 2; // d.x is not a compile-time constant
    }
}

@Setup과 @TearDown

@State 클래스 안에서 @Setup이 표시된 메서드는 측정 전에 실행되고 @TearDown이 표시된 메서드는 이후에 실행됩니다. Level은 실행 빈도를 제어합니다: Trial(한 번), Iteration 또는 Invocation입니다.

import org.openjdk.jmh.annotations.*;

@State(Scope.Thread)
public class Data {
    int[] arr;
    @Setup(Level.Trial)
    public void init() {
        arr = new int[1000];
        for (int i = 0; i < arr.length; i++) arr[i] = i;
    }
}

상수 입력 피하기

테스트 대상 메서드에 리터럴 상수를 직접 입력하지 마십시오. Math.sqrt(2.0)은 상수로 접힐 수 있지만, Math.sqrt(state.value)는 그럴 수 없습니다. 입력은 항상 @State 필드에서 가져오십시오.

여러 값 반환하기

벤치마크에서 자연스럽게 두 결과가 생성된다면 하나는 반환하고 다른 하나는 블랙홀을 통해 소비하거나, 두 결과를 결합할 수 있습니다. 둘 중 하나라도 소비하지 않고 남겨 두면 DCE 문제가 다시 발생합니다.

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;

public class Bench {
    @Benchmark
    public int twoResults(Blackhole bh) {
        int a = 3 * 7;
        int b = 5 + 9;
        bh.consume(b);
        return a;
    }
}

블랙홀 오버헤드

블랙홀은 매우 저렴하고 자체적으로도 최적화에 영향을 받지 않도록 설계되었지만, 비용이 전혀 없는 것은 아닙니다. 매우 빠른 연산에서는 단일 값을 반환하고, 반복문과 여러 값을 처리하는 경우에만 블랙홀을 사용하십시오.

측정값 점검하기

벤치마크가 현실적으로 불가능할 정도로 짧은 시간(실제 작업인데 나노초 미만)을 보고한다면 DCE나 상수 폴딩을 의심하십시오. 결과가 반환되거나 소비되는지, 입력이 @State에서 가져와지는지 다시 확인하십시오.

종합하기

견고한 벤치마크는 @State 객체에서 입력을 읽고, 작업을 수행한 다음, 결과를 return하거나 Blackhole.consume으로 소비합니다. 이 세 가지 습관을 지키면 DCE와 상수 폴딩이 측정값을 왜곡할 수 없습니다.

빠른 확인

죽은 코드 제거를 막는 방법을 제대로 이해했는지 테스트해 보십시오.

복습

벤치마크를 정확하게 유지하는 방법을 배웠습니다.

  • 죽은 코드 제거는 사용되지 않는 계산을 삭제합니다.
  • JMH가 소비할 수 있도록 단일 결과를 반환하십시오.
  • 반복문과 여러 값에는 Blackhole.consume을 사용하십시오.
  • @State 객체는 입력을 불투명하게 유지하여 상수 폴딩을 막습니다.
  • @Setup / @TearDown은 선택한 수준에서 상태를 준비하고 정리합니다.

자주 묻는 질문

“죽은 코드 제거 방지” 강의는 무료인가요?

네 — “죽은 코드 제거 방지” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“죽은 코드 제거 방지”에서 뭘 배우나요?

Blackhole과 상태를 알아봅니다 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“죽은 코드 제거 방지” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. JMH가 필요한 이유
  2. 벤치마크 작성
  3. 워밍업과 반복
  4. 죽은 코드 제거 방지
← Java Academy(으)로 돌아가기