이전에 공부한 조건문과 반복문, 배열과 컬렉션, 메서드와 구조체에 대해서 정리하고
3주차 강의 클래스와 객체, 상속과 다형성, 고급문법 및 기능을 수강 후 정리할 생각이다.
아래 노션 링크에 배웠던 개념을 정리하였다.
아래는 금일 정리한 개념이다.
List는 연속성을 가지고,
LinkedList는 불연속적이다.
여기서 연속성은 무엇을 의미하는 것일까?
연속성이란 메모리 상에서 데이터가 연속된 공간에 배치되어 있는 성질을 의미한다.
예를 들어,
[0x100] → [0x104] → [0x108] → ...[0x100] → [0x1A0] → [0x0F0] → ... (이동 포인터 필요)리스트의 내부 구현은 배열이기에 연속성을 가지고
연결리스트는 노드들이 연결되어 있는 구조로 각 노드는
Next와 Previous 포인터를 통해 연결된다.
따라서 메모리상에 연속성은 없으며
노드를 따라가야 하기 때문에 인덱스로 접근이 불가하고
노드들이 메모리 여기저기 흩어져 있어 캐시 효율이 낮다.
이해를 위한 시각화 예시이다
List<T>:
[10][20][30][40]
↑ ↑ ↑ ↑
0x100 0x104 0x108 0x10C ← 메모리상 연속
LinkedList<T>:
[10] → [20] → [30]
| | |
0x12A 0x1F0 0x0E4 ← 포인터로만 연결, 메모리 주소는 불규칙
C#에서 구조체를 값 타입이다.
값 타입은 메모리에서 연속적으로 배치되는 특성이 있다.
이 말은, 구조체 배열을 만들면 해당 구조체들이 메모라 상에서 서로 인접하게 저장된다는 뜻이다.
예를 들어
struct Point { public float x, y; }
Point[] points = new Point[3];
이렇게 선언한 구조체 배열은 메모라에서 다음과 같이 정렬된다.
[Point(0)] [Point(1)] [Point(2)]
즉, 구조체의 데이터들이 물리적으로 붙어있게 저장된다.
배열처럼 메모리가 연속되어 있으면 CPU는 한 번에 여러 개의 데이터를 불러올 수 있다. 반복문에서 연속적인 데이터를 처리할 때 성능이 크게 향상된다.
for (int i = 0; i < points.Length; i++)
{
points[i].x += 1.0f;
}
위와 같은 반복문은 CPU가 데이터를 예측하여 미리 메모리를 가져올 수 있기 때문에 빠르게 처리된다.
따라서 캐시 효율이 높다.
또한 구조체는 힙이 아닌 스택 또는 고정된 메모리 공간에 저장된다.
클래스를 배열로 만들면 각 요소가 힙 메모리에 따로 생성되므로
GC의 대상이 되고, 메모리 관리가 더 복잡해진다.
하지만 구조체 배열은 스택 또는 연속된 블록에 저장되므로 GC가 신경 쓸 일이 없고, 더 빠르게 생성되고 제거될 수 있다.
반면 클래스 배열은 참조 타입이라서.
배열을 만들어도 실제 데이터는 힙에 흩어져 저장된다.
배열 안에는 객체를 가맄키는 포인터만 저장되며, 각 객체의 위치는 메모리 상 불규칙하게 된다.
그렇다면 Unity에서 이러한 이점을 어떻게 활용할 수 있을까?
내 지식 선에서는 일반 구조체 배열을 활용한 반복 연산 정도 떠올릴 수 있을 것 같다.
struct HitInfo //구조체 선언
{
public Vector3 point;
public float distance;
}
HitInfo hits = new HitInfo[100]; //구조체 배열 생성
for(int i = 0; i<hits.Length; i++)
{
if(hist[i].distance < 5f)
Process(hits[i]);
}
이러한 구조 좀 더 고속 처리가 가능 할 거 같다.
활용 팁으로
나중에 대량 오브젝트로 한번 성능 차이가 있는지 실험해서 노션에 게시해보려 한다