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

Infinite increment of methods-jitted-count counter when using a rule for a full request. #2168

Closed
sergey-rubtsov-05 opened this issue Oct 31, 2023 · 2 comments · Fixed by #2173
Milestone

Comments

@sergey-rubtsov-05
Copy link

FluentValidation version

11.8.0

ASP.NET version

.NET 7

Summary

I met with a strange issue. methods-jitted-count counter increments infinitely if a project has a rule for a full request (not for a property of the request). And it is the only problem, I didn't notice problems with performance or something else.

The first time I saw the problem in my work project which worked with 80 RPS. But I also reproduce the problem in the example project.

Steps to Reproduce

  1. Create a request with at least one property
public record Request(int? Property);
  1. Create a validator with a rule for the request, not for property of request
public class RequestValidator : AbstractValidator<Request>
{
    public RequestValidator() =>
        RuleFor(request => request)
            .Must((request) => request.Property.HasValue);
}
  1. Register the validator as a scoped service
builder.Services.AddScoped<IValidator<Request>, RequestValidator>();
  1. Create a controller with the injected validator and a method which uses it
[ApiController]
[Route("[controller]/[action]")]
public class ExampleController : ControllerBase
{
    private readonly IValidator<Request> _requestWithProblemValidator;

    public ExampleController(IValidator<Request> requestWithProblemValidator) =>
        _requestWithProblemValidator = requestWithProblemValidator;

    [HttpPost]
    public IActionResult Problem(Request request) =>
        _requestWithProblemValidator.Validate(request).IsValid ? Ok() : BadRequest();
}
  1. Start the application
  2. Start monitoring of methods-jitted-count counter in a terminal with the command. On my computer, it shows: Number of Methods Jitted - 1,830
dotnet-counters monitor -p {PID of the ASP.NET application} --counters System.Runtime[methods-jitted-count]
  1. Execute the request 100 times for warming up. Now the counter shows: Number of Methods Jitted - 2,311
  2. Execute the request 100 times to demonstrate the problem. The counter shows: Number of Methods Jitted - 2,411
  3. Execute one more iteration. The counter: Number of Methods Jitted - 2,512. The counter will continue increment for every call.

Expected result

  1. Update the validator code with a rule for a property of request.
public class RequestValidator : AbstractValidator<Request>
{
    public RequestValidator() =>
        RuleFor(request => request.Property)
            .Must((request, _) => request.Property.HasValue);
}
  1. Start the application
  2. Start monitoring of methods-jitted-count counter in a terminal with the command. On my computer, it shows: Number of Methods Jitted - 1,815
  3. Execute the request 100 times for warming up. Now the counter shows: Number of Methods Jitted - 2,229
  4. Execute the request 100 times to demonstrate that the problem does not reproduce. The counter shows: Number of Methods Jitted - 2,229

Also, I attached the project which I used to demonstrate the problem.
FluentValidationMethodJittedProblem.zip

@JeremySkinner
Copy link
Member

JeremySkinner commented Nov 1, 2023

I'm afraid this isn't something that I have time or capacity to look into, so will need someone from the community to investigate further, sorry.

Edit: Oh it'll be because rules are only cached if they're defined against a property. If they're not defined against a property we can't cache them so the expression will have to be recompiled every time the validator is instantiated. If this is a problem for you then you should either rewrite your rule definition not to rely on the root level object, or make your validator singleton-scoped (provided it has no transient or request-scoped dependencies). Its possible we may be able to add caching for root-level expressions in the future, which I will investigate for the next release.

@JeremySkinner JeremySkinner added this to the 11.8.1 milestone Nov 1, 2023
@JeremySkinner JeremySkinner modified the milestones: 11.8.1, 11.8.2 Nov 24, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 9, 2023
@JeremySkinner
Copy link
Member

I've pushed out the 11.9 release which contains support for caching root-level expressions

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

Successfully merging a pull request may close this issue.

2 participants