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

Significant performance issue when Parser.GetDefault() is called repeatedly #73

Open
codinglifestyle opened this issue Mar 29, 2024 · 0 comments

Comments

@codinglifestyle
Copy link

I’ve encountered a significant performance issue with UAParser when it’s used in a logger. The issue arises when Parser.GetDefault() is called repeatedly during large operations. Each call to the logger creates a new instance of the Parser, which leads to a significant performance penalty.

Here’s a simplified test case that demonstrates the issue:

C#

using System;
using System.Diagnostics;
using UAParser;

class Program
{
    const int NumTests = 100;

    static void Main()
    {
        string userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3";

        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < NumTests; i++)
        {
            var parser = Parser.GetDefault();
            var clientInfo = parser.Parse(userAgent);
        }
        stopwatch.Stop();
        Console.WriteLine($"Test Case 1 elapsed time: {stopwatch.ElapsedMilliseconds} ms");

        stopwatch.Restart();
        var parserOutsideLoop = Parser.GetDefault();
        for (int i = 0; i < NumTests; i++)
        {
            var clientInfo = parserOutsideLoop.Parse(userAgent);
        }
        stopwatch.Stop();
        Console.WriteLine($"Test Case 2 elapsed time: {stopwatch.ElapsedMilliseconds} ms");
    }
}

In Test Case 1, Parser.GetDefault() is called 100 times, leading to a total elapsed time of 4046 ms. In Test Case 2, Parser.GetDefault() is called only once, and the same instance is used for all iterations of the loop, resulting in a total elapsed time of 190 ms.

Test Case 1 elapsed time: 4046 ms
Test Case 2 elapsed time: 190 ms

This demonstrates that the time taken to instantiate the Parser object with Parser.GetDefault() is quite significant. It seems that the regex patterns are loaded from the assembly each time Parser.GetDefault() is called.

The actual fix was to instantiate the Parser as a member variable of the logger class, so it’s created only once and reused for all subsequent calls to the logger.

I couldn’t find any explicit warnings or notes about this in the UAParser documentation. It would be helpful if the documentation could provide some guidance or warning about this so others don't repeat the same bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant