

API通信を高速化するためMessagePackを使用したいと考えており  
シリアライズ・デシリアライズの速度がどれだけ違うかを  
MessagePackとJSONを使用して、  
下記処理で速度比較を行っています。

**■追記**  
**計測に誤りがあったのでソースコード書き直し、計測値を再計測  
シリアライズ後のサイズを追加**  

**データ作成→時間計測→シリアライズ→時間計測→デシリアライズ→時間計測**

  
**■使用したMsgPack**

<https://github.com/msgpack/msgpack-cli/releases>

上記URLのバージョン **0.62** 内にあるzipファイルを展開して  
**unity3d** フォルダ内にある **MsgPack.dll** を使用しています。

**■使用したJson**

MiniJSON

**■テストケース**  
１：  
（0-10000までのintのListを１００回シリアライズ・デシリアライズした平均値）を  
Android実機で確認

２：  
（0-10000までのstringのListを１００回シリアライズ・デシリアライズした平均値）を  
Android実機で確認

**■テスト結果**  
■ケース１  
MsgPack（Array）：  
シリアライズ後のバイト数：29747  
シリアライズ時間 ：24.6msec  
デシリアライズ時間：165.2msec

Json：  
シリアライズ後のバイト数：48891  
シリアライズ時間 ：31.1msec  
デシリアライズ時間：74.7msec

■ケース２  
MsgPack（Array）：  
シリアライズ後のバイト数：48893  
シリアライズ時間 ：37.6 msec  
デシリアライズ時間：277.0 msec  
Json：  
シリアライズ後のバイト数：68891  
シリアライズ時間 ：22.2 msec  
デシリアライズ時間：57.5 msec

**■ソースコード**

[code]

    using UnityEngine;
    using System;
    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    using MiniJSON;
    using MsgPack;
    using MsgPack.Serialization;
    using System.Linq;
    
    public class MsgPackAndJsonCompare : MonoBehaviour {
    
    public int SampleCount = 100;
    
    private string MsgLog = "";
    private int SampleIndex = 0;
    
    
    List<long> ArrayListLong = new List<long>();
    List<string> ArrayListString = new List<string>();
    
    
    
    /// <summary>
    /// intデータ作成処理
    /// </summary>
    public void OnClickArrayInt()
    {
        for(int i = 0; i < 10000; i++)
        {
            ArrayListLong.Add(i);
        }
        Debug.Log("OnClickArrayInt End");
    }
    
    
    /// <summary>
    /// Stringデータ作成処理
    /// </summary>
    public void OnClickArrayString()
    {
        for (int i = 0; i < 10000; i++)
        {
            ArrayListString.Add(i.ToString());
        }
        Debug.Log("OnClickArrayString End");
    
    }
    
    
    /// <summary>
    /// 100回ループするテスト開始
    /// </summary>
    /// <param name="sendMode"></param>
    public void OnClickCompare(int sendMode)
    {
        SampleIndex = 0;
    
        for (int i = SampleIndex; i < SampleCount; i++)
        {
            MsgLog = MsgLog + ",LoopCnt=" + i.ToString();
            MsgLog = MsgLog + ",StartTime=" + DateTime.Now.Ticks.ToString();
    
            MainFunc(sendMode);
    
            MsgLog = MsgLog + " ,EndTime=" + DateTime.Now.Ticks.ToString() + "\n";
        }
    
        Debug.Log("Function End");
    
    
    }
    
    /// <summary>
    /// メイン処理
    /// </summary>
    /// <param name="compareMode"></param>
    private void MainFunc(int compareMode)
    {
        // ArrayInt-MsgPack
        if (compareMode == 0)
        {
            MsgLog = MsgLog + ",シリアライズStartTime=" + DateTime.Now.Ticks.ToString();
            var stream = new MemoryStream();
            // Create serializer instance.
            var serializer = MessagePackSerializer.Get<List<long>>();
            serializer.Pack(stream, ArrayListLong);
    
            //long datalen = stream.Length;
    
            MsgLog = MsgLog + ",シリアライズEndTime=" + DateTime.Now.Ticks.ToString();
            stream.Position = 0;
            List<long> deserializedObject = serializer.Unpack(stream);
            MsgLog = MsgLog + ",デシリアライズEndTime=" + DateTime.Now.Ticks.ToString();
        }
        // ArrayInt-Json
        else if (compareMode == 1)
        {
            MsgLog = MsgLog + ",シリアライズStartTime=" + DateTime.Now.Ticks.ToString();
            string serialized = Json.Serialize(ArrayListLong);
    
            int ilenb = System.Text.Encoding.GetEncoding(65001).GetByteCount(serialized);
    
            MsgLog = MsgLog + ",シリアライズEndTime=" + DateTime.Now.Ticks.ToString();
            List<System.Object> deserializedDoubleList = Json.Deserialize(serialized) as List<System.Object>;
            List<long> longList = deserializedDoubleList.OfType<long>().ToList();
            MsgLog = MsgLog + ",デシリアライズEndTime=" + DateTime.Now.Ticks.ToString();
    
        }
        // ArrayString-MsgPack
        else if (compareMode == 2)
        {
            MsgLog = MsgLog + ",シリアライズStartTime=" + DateTime.Now.Ticks.ToString();
            var stream = new MemoryStream();
            // Create serializer instance.
            var serializer = MessagePackSerializer.Get<List<string>>();
            serializer.Pack(stream, ArrayListString);
    
            long datalen = stream.Length;
    
            MsgLog = MsgLog + ",シリアライズEndTime=" + DateTime.Now.Ticks.ToString();
            stream.Position = 0;
            List<string> deserializedObject = serializer.Unpack(stream);
            MsgLog = MsgLog + ",デシリアライズEndTime=" + DateTime.Now.Ticks.ToString();
        }
        // ArrayString-Json
        else if (compareMode == 3)
        {
            MsgLog = MsgLog + ",シリアライズStartTime=" + DateTime.Now.Ticks.ToString();
            string serialized = Json.Serialize(ArrayListString);
    
            int ilenb = System.Text.Encoding.GetEncoding(65001).GetByteCount(serialized);
    
            MsgLog = MsgLog + ",シリアライズEndTime=" + DateTime.Now.Ticks.ToString();
            List<System.Object> deserializedDoubleList = Json.Deserialize(serialized) as List<System.Object>;
            List<string> longList = deserializedDoubleList.OfType<string>().ToList();
            MsgLog = MsgLog + ",デシリアライズEndTime=" + DateTime.Now.Ticks.ToString();
    
        }
    }
    
    
    public void OnclickLog()
    {
        StartCoroutine(LogDisp());
    
    }
    
    
    IEnumerator LogDisp()
    {
        string[] LogArray = MsgLog.Split('\n');
    
        int maxloop = LogArray.Length;
        int i = 0;
        while (i < maxloop)
        {
            Debug.Log("Log=" + LogArray[i]);
    
            yield return 0;
    
            i++;
    
        }
    }
    
[/code]

■問題点  
ネットなどで情報を集めているとMessagePackの方が早いという記述が  
多くみられるのですが、私のソースではMessagePackで処理するよりも  
JSONの方が速度が速いため、やり方が間違っているのではと疑っています。


CC BY-SA 3.0
2015-09-04T05:14:45.883
16224
2015-09-07T07:29:36.410
2015-09-07T06:03:23.127
5261
5261
question
c# unity3d json
MessagePackのシリアライズ・デシリアライズ時間がJsonよりが遅くなる


シリアライズとは入力データをバイナリなどに変換することです。  
デシリアライズとはその逆でバイナリなどを入力データの形に戻すことです。

`MessagePackSerializer`は`List<int>`をシリアライズし、また`List<int>`へとデシリアライズしています。  
しかし`Json.Serialize`は`List<int>`をシリアライズはしますが、`Json.Deserialize`は`List<int>`へとは戻しておらず、JSON文字列をデコードしかしていません。（返されるのは`object[]`かな？）

ですので対等な比較になっていません。

* * *

さっぱり通じていないようなので追記します。  
`MessagePackSerializer`は条件を満たせば任意の型対応しています。例えば

[code]

    public struct Color {
        public int R;
        public int G;
        public int B;
        public override string ToString() { return "Hoge"; }
    }
    
[/code]

を渡しても型を解釈し、パブリックプロパティをシリアライズしますし、デシリアライズ時には各プロパティ値を復元したものを返します。  
対して`MiniJSON`は、型を維持しません。[未知の型に対してはToString()](https://gist.github.com/darktable/1411710#file-
minijson-cs-L542)した結果をシリアライズしますし、数値は`double`や`int64`にデシリアライズします。  
結果、`MiniJSON`で上記`Color`をシリアライズするとJSON文字列は `"Hoge"`
になりますし、デシリアライズしても文字列しか得られません。

ですので対等な比較になっていません。


CC BY-SA 3.0
2015-09-05T05:22:32.550
16279
2015-09-07T07:29:36.410
2015-09-07T07:29:36.410
4236
4236
16224
answer