- BigInteger 구현을 하면서 최적화 하기 위한 방법을 찾던중 Span
라는 문법을 발견.
Span<T>
란?
Span<T>
는 C# 7.2에서 도입된 구조체로, 연속된 메모리 영역을 안전하고 효율적으로 처리할 수 있도록 도와줌. Span<T>
는 기본적으로 배열, 문자열, 혹은 포인터와 같은 연속된 메모리 공간에 대한 뷰를 제공함. 이를 통해 메모리를 복사하지 않고도 데이터를 조작할 수 있어 성능을 크게 개선할 수 있음.
기본적인 특징은 다음과 같음:
- 메모리 안전성:
Span<T>
는 배열을 다룰 때 흔히 발생할 수 있는 인덱스 범위 초과 문제에 대해 안전한 처리를 제공. - 힙 할당 회피:
Span<T>
는 스택에 할당되어 GC(가비지 컬렉션)의 부담을 줄이므로, 특히 성능이 중요한 코드에서 유용. - 범용성:
Span<T>
는 배열뿐만 아니라 메모리의 특정 구역을 다루는 데도 사용할 수 있음. 문자열 조작이나 네이티브 메모리와의 상호작용에서도 효율적.
왜 Span<T>
를 사용해야 할까?
대부분의 경우, 배열과 같은 데이터를 조작할 때 메모리 복사가 성능 저하의 원인이 될 수 있음. 예를 들어, 큰 배열에서 일부 구간만 처리하고 싶을 때, 기존에는 부분 배열을 새로 생성하여 복사하는 방법을 사용. 그러나 이 과정에서 추가적인 메모리 할당과 복사가 발생해 성능이 저하될 수 있음.
Span<T>
를 사용하면 이러한 문제를 해결할 수 있음. Span<T>
는 원본 데이터를 가리키는 뷰만 생성하므로 메모리 할당 없이도 부분 데이터를 효율적으로 조작할 수 있음.
Span<T>
사용 예제
using System;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 배열의 일부를 나타내는 Span 생성
Span<int> part = new Span<int>(numbers, 2, 5); // 인덱스 2부터 5개의 요소
// Span을 이용해 데이터 수정
for (int i = 0; i < part.Length; i++)
{
part[i] *= 2;
}
// 결과 출력
Console.WriteLine(string.Join(", ", numbers));
}
}
위 예제에서는 numbers
배열에서 인덱스 2부터 시작하는 5개의 요소에 대한 Span
을 생성하고, 이를 이용해 해당 요소들의 값을 두 배로 증가. Span
을 통해 데이터를 변경하면 원본 배열도 함께 수정됨. 이는 메모리 복사 없이 원본 데이터를 직접 다루기 때문에 가능.
ReadOnlySpan<T>
Span<T>
의 읽기 전용 버전인 ReadOnlySpan<T>
도 있음. 이는 데이터를 변경할 필요가 없을 때 사용되며, 안전한 읽기 작업만을 제공함. 예를 들어 문자열을 조작할 때, 복사 없이 읽기 전용으로 사용하고자 할 때 매우 유용.
주의 사항
Span<T>
는 스택 할당을 사용하기 때문에 메서드나 함수 범위를 벗어나면 사용할 수 없음. 따라서Span<T>
를 필드로 저장하거나 비동기 메서드에서 직접 사용할 수 없음.Span<T>
는 포인터와 유사한 방식으로 메모리에 접근하지만, 안전성을 제공하기 때문에 포인터의 복잡함 없이도 효율적으로 메모리를 관리할 수 있음.
'Language > C#' 카테고리의 다른 글
[C#] Skip (0) | 2024.11.06 |
---|---|
[C#] Reflection - MemberInfo/FieldInfo / PropertyInfo (0) | 2024.10.30 |
[C#] Const와 Readonly (0) | 2024.10.14 |
[C#] Serialization & Deserializaton (0) | 2024.10.14 |
[C#] String Builder (0) | 2024.10.14 |