본문 바로가기
프로그래밍/Game Dev

[C#] MessagePack

by YuminK 2023. 8. 26.

MessagePack
https://github.com/MessagePack-CSharp/MessagePack-CSharp

Serializer for C#
퍼포먼스가 중요한 게임, 분산 컴퓨팅, 마이크로 서비스, 데이타 캐시 목적으로 사용된다.

사용 방법
Serialize 하길 원하는 class 또는 struct에 [MessagePackObject]를 붙인다.
처리되어야 하는 필드에 [Key] 속성을 붙인다.
처리하길 원하지 않는 필드에 [IgnoreMember] 속성을 붙인다 

[MessagePackObject]
public class MyClass
{
    // Key attributes take a serialization index (or string name)
    // The values must be unique and versioning has to be considered as well.
    // Keys are described in later sections in more detail.
    [Key(0)]
    public int Age { get; set; }

    [Key(1)]
    public string FirstName { get; set; }

    [Key(2)]
    public string LastName { get; set; }

    // All fields or properties that should not be serialized must be annotated with [IgnoreMember].
    [IgnoreMember]
    public string FullName { get { return FirstName + LastName; } }
}

MessagePackSerializer.Serialize<T>/Deserialize<T> 호출을 통해 직렬화/역직렬화 과정을 거칠 수 있다. 
ConvertToJson 메소드를 통해 읽을 수 있는 데이터로 만들 수도 있다.

class Program
{
    static void Main(string[] args)
    {
        var mc = new MyClass
        {
            Age = 99,
            FirstName = "hoge",
            LastName = "huga",
        };

        // Call Serialize/Deserialize, that's all.
        byte[] bytes = MessagePackSerializer.Serialize(mc);
        MyClass mc2 = MessagePackSerializer.Deserialize<MyClass>(bytes);

        // You can dump MessagePack binary blobs to human readable json.
        // Using indexed keys (as opposed to string keys) will serialize to MessagePack arrays,
        // hence property names are not available.
        // [99,"hoge","huga"]
        var json = MessagePackSerializer.ConvertToJson(bytes);
        Console.WriteLine(json);
    }
}

모든 키가 인덱싱이 된 경우, 배열이 사용되고(퍼모먼스 증가) 아니라면 딕셔너리가 사용된다.
private와 내부 구조체는 직렬화되지 않는다. 

MessagePackObject 어노테이션은 명시성을 강요한다.

더 빠른 속도를 위해 string 키보다 인덱스 키를 권장한다. (string키의 경우 디버깅에 도움이 될 수 있다) 

상속을 받을 때 버전닝에 주의해야 한다. MessagePackSerializer는 default 값으로 초기화를 한다. (직렬화된 이진 blob에 없는 경우)
=> 레퍼런스 타입의 경우 null로 초기화될 수 있다.

인덱스 키를 사용한다면 0부터 시작하고 순차적이어야 한다. 이후 버전에서 고정된 멤버를 사용하지 않는 경우, 이전 데이터를 남겨야 한다. (주석을 위한 Obsolete 어노테이션을 제공한다.)


시퀀스에 갭을 남기는 것은 사이즈에 부정적인 영향을 줄 수 있으며, null도 array에 들어가게 된다. 삭제된 멤버의 인덱스를 재사용하지 말아야 한다. (직렬화 레거시 블롭 이슈)

'프로그래밍 > Game Dev' 카테고리의 다른 글

[C#] SpinLock  (0) 2023.08.26
[C#] Interlocked  (0) 2023.08.26
[C#] 메모리 베리어  (0) 2023.08.26
[C#] 캐시 메모리 철학  (0) 2023.08.26
[C#] 쓰레드 생성  (0) 2023.08.26

댓글