BinaryFormatter serialization very different times for different classes

56 Views Asked by At

I am using BinaryFormatter to send different message types via TCP.

I use the following code to transmit a MessageBase derived class:

private void TransmittingThread()
{
    log.Debug("TCPCommunicationLayer - TransmittingThread Startting");

    while (IsRunning)
    {
        try
        {
            // This blocks until a message is available
            MessageBase msg = MessageQueue.Take();

            if (msg != null)
            {
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();

                BinaryFormatter f = new BinaryFormatter();
                MemoryStream ms = new MemoryStream();
                f.Serialize(ms, msg);

                long msgSize = ms.Length;
                log.Debug($"Transmitting - {msg.Report(true)} - {msgSize} Bytes - {stopWatch.ElapsedMilliseconds} ms");
                f.Serialize(_client.GetStream(), msg);
                stopWatch.Stop();

                log.Debug($"Transmitted - {msg.Report(true)} - {stopWatch.ElapsedMilliseconds} ms");
                ms.Close();
            }
        }
        catch (Exception e)
        {
            log.Error(e);
            Disconnect();
        }
    }

    while (MessageQueue.TryTake(out _)) { }

    log.Debug("TCPCommunicationLayer - TransmittingThread Exiting");
}

MessageBase is defined as:

[Serializable]
public abstract class MessageBase
{
    protected MessageBase(string name)
    {
        Name = name;
        Guid = Guid.NewGuid();
    }

    public Guid Guid { get; }
    public string Name { get; }
}

[Serializable]
public class ParameterMessage<T> : MessageBase
{
    public ParameterMessage(string name, T data)
        : base(name)
    {
        Data = data;
    }

    public T Data { get; }
}

The following class which is about 5 Mb in size takes about 500 ms to transmit:

[Serializable]
public class SharedPreview : SharedPreviewParameters
{
    private byte[] _previewImageBuffer = Array.Empty<byte>();
    private byte[] _labelImageBuffer = Array.Empty<byte>();

    public SharedPreview(ScanInfo scanInfo, List<RegionOfInterest> regionsOfInterest, List<PredictiveFocusPoint> predictiveFocusPoints)
        : base(scanInfo, regionsOfInterest, predictiveFocusPoints)
    {
    }

    private byte[] EncodeImage(BitmapImage image)
    {
        // ...
    }

    private BitmapImage ExtractImage(byte[] buffer)
    {
        // ...
    }
}

But the following class which is only 200 Kb takes about 20 seconds:

[Serializable]
public class ClientLogDefinition
{
    public string Filename { get; set; }
    public string FullPath { get; set; }
    public string Content { get; set; }
}

[Serializable]
public class SharedClientLogs
{
    public List<ClientLogDefinition> ClientLogs { get; } = new List<ClientLogDefinition>();
}

I realize I could convert the strings to byte arrays which might solve the issue but I would really like to know what is causing the very slow performance with large strings

0

There are 0 best solutions below