skbkontur / GroBuf

Fast binary serializer
MIT License
64 stars 10 forks source link

How to improve the first serialization #23

Closed JasonIonke closed 4 years ago

JasonIonke commented 4 years ago

GroBuf is a quite nice serialization tool which is much faster than protobuf. In my test case, one serialization takes only around 20us. But for every types(primitive type and custom type), the first time run takes about 100ms. I found it is caused by BuildWriter which is dynamically create method in the first time.

Is it possible to speed up that part? For eg, maybe we could create methods for known type in build time and so can reduce 100ms in runtime?

Anton92nd commented 4 years ago

Hi! Is this really a problem? 100ms is not so painful to wait for the first time. Is seems to me that it would be easier for you to warmup your application before doing it's real work.

In other words, you can declare some class with all primitive and custom type properties you need and seriealize it. Then you can start handling requests or do other important things with your application.

JasonIonke commented 4 years ago

Thanks @Anton92nd . 100ms is not much for one type but my case has dozens of types. From your suggestion, I think I could write code for types which need to be serialized other than use dynamic IL generation. Am I right?

If so, could you kindly share one sample to how to handle own declared class with primitive or custom types? Appreciated for your reply

Anton92nd commented 4 years ago

I think you got me wrong. What I meant is something like this:

public class GrobufWarmupTypes
{
    public TypeA A { get; set; }
    public TypeB B { get; set; }
    ... // make list of all of your dozens of types
}

public class MyApplicationEntryPoint
{
    public static void Main()
    {
        var serializer = new Serializer(new AllPropertiesExtractor());
        var bytes = serializer.Serialize(new GrobufWarmupTypes());
        serializer.Deserialize<GrobufWarmupTypes>(bytes); // if you need to warmup readers as well

        RunApplication(serializer);
    }
}
JasonIonke commented 4 years ago

Thanks again for the suggestion @Anton92nd. I've got what you mean. I will try GrobufWarmupTypes.

Another way I am thinking is instead of warmup, maybe I could hand-code for these types instead of dynamic IL generation. Therefore, in build time I would have the all the codes and no need IL generation. Is it possible? I have read your code and want to revert IL code back to C# but IL seems difficult for me to understand.

Anton92nd commented 4 years ago

It is possible, but we don't think it's a good idea to implement this feature in GroBuf. It would be unnecessary complexity that we want to avoid.

In current implementation all emitted code gets compiled into dynamic assembly. If you build static assembly with all required readers, writers and size counters, then, theoretically, you can modify GroBufWriter.GetWriterAndSizeCounter code so it would check your static assembly first and emit & compile code dynamically only if it has found nothing.