Home .NET 10 런타임 개선사항 요약
Post
Cancel

.NET 10 런타임 개선사항 요약

.NET 10 런타임 개선사항 요약

.NET8 이후로 개선사항을 잘 모르기도하고.. 팀원들한테 변경점 정도는 공유하면서 업데이트 하자고 말씀드리고 싶어서 요약..

1. 코드 구문 분석 개선(관련 이슈)

1.1 Flog Grpah 기반 분석

JIT가 코드를 분석할 때 기존의 Lexcial Ordering(어휘 순서)기반 분석에서 Flow Graph 기반 분석 방식으로 개선하여 선형적으로만 분석하지 않고 그래프 플로우를 따라가며 분석하여 기존보다 복잡한 루프문(다중 탈출문, 예외 처리 등이 포함된) 분석이 가능해짐.

1.2 Escape 분석

객체가 생성된 함수보다 오래 살아남거나, 지역 변수가 아닌 변수의 멤버로 할당되면 Escape 되는데, 이를 JIT에서 분석하여 Unescape 되는 경우 스택에만 메모리를 할당할 수 있도록 최적화 진행한다. 새로 도입된 기능은 아니고 위 Flow Graph 기반 분석을 통해 더욱 개선했다는 내용.

2. Escape 분석 & Stack Allocation 개선

2.1 Boxing 개선

.NET9 부터 생명주기를 확인하여 Unescape 박싱은 스택에서 처리할 수 있도록 일부 최적화가 이루어짐.

  • 상세 내용: Compare 함수가 RunIt으로 인라이닝되고, Unescape 박싱을 최적화해서 제거해버리고, 본문도 제거하고 Equals만 남기고, int형에 3이랑 4인것도 알고 컴파일시간에 false 인것도 알아버려서 그냥 return 100 하나만 남김.
2.2 Small Array 개선

작은 크기의 배열이 Unescape인 경우, stack alloc 처리함. Enumerator 구현 방식 때문에 기존에는 못했던 최적화였으나 .NET 10 부터 최적화가 가능해짐.

static void Print()
{
    string[] words = {"Hello", "World!"}; // on stack
    foreach (var str in words)
    {
        Console.WriteLine(str);
    }
}
2.3 Struct Member 개선

Struct의 멤버로 객체가 들어가 있어도 Unescape일 경우 힙할당이 발생하지 않음.

public class Program
{
    struct GCStruct
    {
        public int[] arr;
    }

    public static int Main()
    {
        int[] x = new int[10];
        GCStruct y = new GCStruct() { arr = x };
        return y.arr[0];
    }
}
2.4 Delegate 개선

delegate 생성 시 클로저 & func 임시 객체가 생성되는데, Unescape인 경우 func를 위한 힙 할당이 발생하지 않음. (클로저 객체는 아직 힙 할당이지만 개선 예정..)

public static int Main()
{
    int local = 1;
    int[] arr = new int[100]; // stack alloc
    var func = (int x) => x + local; // stack alloc
    int sum = 0;

    foreach (int num in arr) // IEnumerable -> for 인라이닝
    {
        sum += func(num);
    }

    return sum;
}
2.5 Loop Inversion 개선

Flog Graph 개선으로 반복문 내에 다중 exit이 있거나 exception이 있는 경우에도 루프 반전 최적화를 진행할 수 있도록 개선됨.

  • 조건에 맞는 경우에만 조건부 분기하는 명령어를 사용함으로써 일반 while문에 비해 매 루프마다 분기 명령어 1개가 절약됨.
  • CPU 정적 분기 예측에 되돌아가는 분기는 보통 반복문이고 이후에도 실행될 가능성이 높다고 판단하는 분기 예측 특성과 일치하게 되어 파이프라이닝 최적화에 도움이 됨.
  • 루프 반전을 통해 범위 검사 제거, 불변식 이동과 같은 다른 최적화를 진행하는 기반이 마련됨.

3. 탈추상화(De-Abstraction) 개선

배열을 순회하는 경우에 인터페이스를 사용할 경우 Enumerator 객체 생성, try-finally 구문 추가, MoveNext()와 같은 Virtual 함수를 호출하는 등의 Penalty가 존재하였고 이를 제거하기 위해 다음과 같은 개선사항이 포함됨.

  • dynamic PGO 개선: 인터페이스의 실제 타입을 추론하는데 도움을 줌
  • stack allocation 개선: 탈추상화와 연관되어 시너지를 줌
  • loop cloning: 루프를 fast/slow 버전으로 만들어 특정 분기에서 속도 향상
  • physical promotion (특정 상황에서 스택도 사용하지않고 레지스터를 바로 사용)
This post is licensed under CC BY 4.0 by the author.

태초마을로 돌아가자 - 게임서버 스터디 발표(1)

-