더북(TheBook)

스팬을 사용하는 이유를 다시 한 번 상기해 보자. 스팬을 사용하는 이유는 힙 할당을 줄이고 복사가 이루어지는 것을 피하기 위함이다. 람다 표현식이 매개변수나 지역 변수를 캡처하면, 람다 표현식은 내부적으로 클래스를 생성하고 이 클래스 타입으로 인스턴스를 생성한다. 그리고 이 인스턴스를 통해 캡처된 변수들의 값을 이용한다. 그런데 예제 13-23의 람다 표현식은 어떤 변수도 캡처하지 않기 때문에 컴파일러는 이 람다 표현식을 정적 메서드로 생성할 수 있으며, Generate가 여러 번 호출되더라도 단 하나의 델리게이트 인스턴스만을 캐시하여 사용할 수 있게 된다. 그리고 모든 상태 정보는 string.Createstate 매개변수를 통해서만 전달된다. 게다가 C# 7의 튜플은 값 타입이므로 state를 위해 튜플을 생성하더라도 힙 할당이 수행되지 않는다.

이제 랜덤 문자열 생성 메서드가 기대 수준에 도달한 것 같다. 힙 할당은 한 번으로 충분하고 추가적으로 데이터 복사를 수행하지도 않는다. 사용자 코드에서는 문자열 내부에 값을 직접 쓴다.

이 예제는 Span<T>를 이용하는 단순한 예에 지나지 않는다. Span<T> 외에도 이와 관련된 다양한 타입이 존재하는데, ReadOnlySpan<T>, Memory<T>, ReadOnlyMemory<T> 등이 가장 중요한 타입들이다. 각각의 타입에 대해 세부적으로 설명하는 것은 이 책의 범위를 벗어난다.

Generate 메서드를 최적화하는 과정에서 이 메서드의 원형을 변경하지 않았다는 점도 중요한 부분이다. 코드의 다른 부분에 영향을 미치지 않고, 내부적인 구현 방식만을 변경해서 최적화를 수행할 수 있다는 점은 상당히 매력적으로 보인다. 크기가 큰 구조체를 사용할 때는 코드 전반에 걸쳐 구조체의 참조를 전달하도록 수정할 수도 있지만, 최적화를 위해 너무 많은 코드를 수정해야 하는 꼴이 된다. 따라서 지금처럼 다른 코드에 영향을 미치지 않고 제한된 코드만을 최적화하는 방식이 훨씬 더 낫다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.