System.Runtime.InterOpServices.Marshal을 사용하여 byte array로 변환하는 방법도 고려해볼 수 있다.
이 방법은 특히 관리되지 않는 형식, 즉 int, float 등으로만 구성된 클래스를 저장하고 읽을 때 빠른 속도를 보여준다. 데이터의 형식에 따라 상당히 달라질 수 있지만 json보다도 3~5배가량의 속도 향상을 기대해볼 수 있다.
Marshal은 프로그램이 다른 프로그램에서 사용할 수 있도록 데이터를 전송하는 것을 의미하는데, Marshal을 하려면 직렬화를 하는 경우가 많다. 따라서 .NET에서는 Marshal.StructureToPtr과 Marshal.PtrToStructure를 이용해 간단히 클래스를 byte array로 직렬화하는 메소드를 제공한다.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Row
{
public int A;
public float B;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string C;
}
public class Data
{
public List<Row> Rows;
}
public static class Testbed
{
public static Data LoadBytes(byte[] bytes, int rowCount)
{
var rowSize = Marshal.SizeOf(new Row());
IntPtr buffer = Marshal.AllocHGlobal(rowSize);
var dataSet = new Data();
for (var i = 0; i < rowCount; i++)
{
Marshal.Copy(bytes, i * rowSize, buffer, rowSize);
dataSet.Rows.Add(Marshal.PtrToStructure<Row>(buffer));
}
Marshal.FreeHGlobal(buffer);
return dataSet;
}
}
개인적으로 Marshal을 사용하여 직렬화 하는 것은 추천하지는 않는 방법이다.
그냥 가능은 하다 정도로 생각하는게 좋을 것 같다.
이유는 여러가지가 있는데, 일단 .NET Marshal이 애초에 대량의 데이터를 직렬화하려고 만든것이 아니기 때문에 제약도 많고, API 디자인도 적합하지 않다. 예를 들어 List<T> 등을 직접 직렬화 할 수 없고, PtrToStucture가 이름에 걸맞지 않게 struct에는 사용할 수 없다는 점,
또한 여러가지 제약이 붙는데, 필드간의 순서를 고정하기 위해 [StructLayout(LayoutKind.Sequential, Pack = 1)] 특성이 필요하며, string은 관리되는 형식이니만큼 직접 직렬화할 수 없다. 다행히 .NET에는 string을 고정 길이 바이트 배열로 직렬화하는 기능이 내장되어 있지만, [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 같은 특성을 string마다 덕지덕지 붙여야 하며 고정길이를 넘어가지 않는지도 신경써야 하고, 만약 길이를 넉넉하게 잡는다면 엄청난 양의 디스크 및 메모리가 낭비될 수 있다.
장점
- 빠르다.
- 비교적 적은 코드 수정으로 속도를 크게 끌어올릴 수 있다..
단점
- 문자열 저장이 비효율적이다.
- 이런저런 특성을 덕지덕지 붙여야 한다.
- 타입으로 struct를 사용할 수 없다.
- List/Array를 통째로 저장하고 불러오는 로직은 직접 만들어야 한다. (첫 4바이트를 행의 갯수를 저장하는데 쓴다던가)
'Unity' 카테고리의 다른 글
Unity의 fake null 문제 (0) | 2023.09.26 |
---|---|
MonoBehaviour의 초기화는 어떻게 해야 하는가? (0) | 2023.09.06 |
유니티에서 테이블 데이터 로드하기 #4 - Source Generator (0) | 2023.09.01 |
유니티에서 테이블 데이터 로드하기 #2 - CSV (0) | 2023.08.17 |
유니티에서 테이블 데이터 로드하기 #1 - JSON (0) | 2023.08.16 |