Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow initial startup serializer/deserializer #2477

Closed
Sieuwkje-firely opened this issue May 26, 2023 · 7 comments
Closed

Slow initial startup serializer/deserializer #2477

Sieuwkje-firely opened this issue May 26, 2023 · 7 comments

Comments

@Sieuwkje-firely
Copy link

Sieuwkje-firely commented May 26, 2023

Note
Created for Behrouz Rad who emailed this issue to the Firely Server mailbox

Describe the bug

I use the SDK in a .NET Core Web API Service app that runs on an EC2 amazon instance.
The service runs during the startup of the server. When the service receives the very first request, any methods of the SDK like SearchAsync or CreateAsync takes nearly 6 seconds to be completed.

From the second request on, these methods run fast.
May you have any idea on improving the first call to the APIs?

Additional context
I tried different techniques like compilation with R2R mode or using IHttpClientFactory for FhirClient and disabling IPV6, but no chance.

@Sieuwkje-firely
Copy link
Author

The slow first call could be caused by the initial startup of the serializer/deserializer. This should normally take milliseconds, but there could be something in the environment that slows that process down.

@ewoutkramer
Copy link
Member

Let's see it we can isolate the problem. Can you replace the FhirClient calls with a simple serializer/deserializer call? Like the code on top of this page: https://docs.fire.ly/projects/Firely-NET-SDK/parsing/poco-parsing.html

Also: which version of the SDK are you using?

@Sieuwkje
Copy link

Sieuwkje commented May 26, 2023

Note from Behrouz:

I managed to solve the issue.
It seems it's an issue regarding the HttpClient in .NET Core.
It needs a warm-up. So during the startup I did something like this:

In Program.cs

    builder.Services.AddHttpClient("FhirHttpClient")
                      .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
                      {
                        AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
                        ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
                      })
                      .AddHttpMessageHandler<AuthorizationMessageHandler>();

    builder.Services.AddTransient(ctx =>
    {
      var httpClient = ctx.GetRequiredService<IHttpClientFactory>()
                          .CreateClient("FhirHttpClient");

      var settings = new FhirClientSettings
      {
        Timeout = 5000,
        PreferredFormat = ResourceFormat.Json,
        VerifyFhirVersion = false
      };

      return new FhirClient(FHIR_SERVER_ADDRESS, httpClient, settings);
    });
.
.
.
    app.Lifetime.ApplicationStarted.Register(async () =>
    {
      await app.WarmUpHttpClients(app.Services, builder.Services);
    });

In WarmUpHttpClients method (A fake request):

var fhirClient = app.ApplicationServices.GetRequiredService<FhirClient>();
await fhirClient.SearchAsync<Practitioner>();

@ewoutkramer
Copy link
Member

One more possible thing is that the first thing the FhirClient does (and it does this once!) is check the version of the server it is communicating with. If this is a slower server or connection (the CapabilityStatements can be HUGE), than this is certainly a problem. There is a FhirClient setting to not perform this check - @Sieuwkje this might be worth checking out if this is still relevant.

Oteherwise, it's hard for us to reproduce, and I am positively sure that if this was a general problem, we would get many more reports about this issue.

@brianpos
Copy link
Collaborator

brianpos commented Aug 7, 2023

This is more likely that loading of all the classmapping objects via the ModelInspector through reflection in the serializer - which is only done once.
Doing a fake read will result in preparing the ModelInspector so that it's all set to go.
So doing a simple parse of anything would ensure that was all loaded.
even something as simple as might do the trick.

var patString = new Patient().ToXml();

Maybe the httpclient also could use some warming, but the preparation in the ModelInspector has taken its time in the past.

@marcovisserFurore
Copy link
Member

@Sieuwkje-firely, is this still an issue? Otherwise, I am going to close it.

@Sieuwkje-firely
Copy link
Author

Sorry, yes this issue can be closed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

5 participants