BaseClientService.Initializer creates s new instance of NewtonsoftJsonSerializer each time a new instance of BaseClientService is created (see), which in turn creates a new instance of JsonSerializerSettings (see).
Newtonsoft library produces and JITs lambdas dynamically to improve (de)serialization performance for each type it observes, but the library caches these compiled lambdas by JsonSerializerSettings object used when these types were observed. So each time a new instance of JsonSerializerSettings is used, the library generates and compiles new lambdas since it's not reusing previously generated and compiled instances.
This means each time we create a new instance of BaseClientService and make an API call, we will be generating a new set of lambdas and compile them at runtime and if we scope BaseClientService to a single user request, a lot of JITTING will happen. Here's an example captured using dotnet trace and loaded in PerfView:
If the following line is changed from (see my previous links):
Serializer = new NewtonsoftJsonSerializer();
To:
Serializer = NewtonsoftJsonSerializer.Instance;
The problem would be gone. I guess you could also extend factory methods for all API clients to accept instance of NewtonsoftJsonSerializer to be used, or at least instance of JsonSerializerSettings, but that would be such a drag and error prone approach.
BaseClientService.Initializercreates s new instance ofNewtonsoftJsonSerializereach time a new instance ofBaseClientServiceis created (see), which in turn creates a new instance ofJsonSerializerSettings(see).Newtonsoftlibrary produces and JITs lambdas dynamically to improve (de)serialization performance for each type it observes, but the library caches these compiled lambdas byJsonSerializerSettingsobject used when these types were observed. So each time a new instance ofJsonSerializerSettingsis used, the library generates and compiles new lambdas since it's not reusing previously generated and compiled instances.This means each time we create a new instance of
BaseClientServiceand make an API call, we will be generating a new set of lambdas and compile them at runtime and if we scopeBaseClientServiceto a single user request, a lot of JITTING will happen. Here's an example captured usingdotnet traceand loaded inPerfView:If the following line is changed from (see my previous links):
To:
The problem would be gone. I guess you could also extend factory methods for all API clients to accept instance of
NewtonsoftJsonSerializerto be used, or at least instance ofJsonSerializerSettings, but that would be such a drag and error prone approach.