-
-
Notifications
You must be signed in to change notification settings - Fork 978
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
Op/Invocation count not scaling up #994
Comments
Just to add, you can simplify my benchmark example above by just directly performing a HTTP request on the client from the test server like so: [Benchmark]
public async Task ExampleBenchmark()
{
await TestSite.GetHttpClient().GetAsync(new Uri("http://localhost/"));
} |
I've started to investigate this issue in a clean solution and am finding more strange quirks related to the above. I don't believe the issue is library specific anymore but maybe in some strange way the code is getting compiled and analysed by BDN? In a MVCE, I have been able to reliably create this issue for CLR: using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace TestServerBenchmarkTests
{
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<TestBenchmark>();
}
}
[CoreJob, ClrJob(baseline:true)]
[MemoryDiagnoser]
public class TestBenchmark
{
private TestServer Server { get; }
private HttpClient Client { get; }
public TestBenchmark()
{
var builder = new WebHostBuilder()
.UseStartup<EmptyStartup>();
Server = new TestServer(builder);
Client = Server.CreateClient();
}
//[Benchmark]
//public void TestServerAndCreateClient()
//{
// var builder = new WebHostBuilder()
// .UseStartup<EmptyStartup>();
// var testServer = new TestServer(builder);
// var client = testServer.CreateClient();
//}
[Benchmark]
public async Task CreatedOnceTestServer()
{
await Client.GetAsync("http://localhost");
}
}
class EmptyStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore();
}
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory())
});
app.UseMvcWithDefaultRoute();
}
}
} <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.11.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
</ItemGroup>
</Project> With the benchmark "TestServerAndCreateClient" commented out, that second benchmark "CreatedOnceTestServer" will create the issue I described above about not scaling the ops/invocation count automatically. It gets strange because if you uncomment out "TestServerAndCreateClient", the issue disappears! The two benchmarks do not touch the same instances of the classes yet somehow are impacting each other. |
An even more simple difference than the two benchmarks, just commenting out |
I have the same issue. Also tried with |
@Turnerj @ycrumeyrolle you are most probably experiencing #837 A workaround would be to call the benchmark once from the [GlobalSetup]
public async Task Setup()
{
TestSite = new TestSiteManager(new SiteContext
{
SiteFolder = "BasicSite"
});
var client = TestSite.GetHttpClient();
Crawler = new Crawler(client, new ParallelAsyncTaskHandler());
await CrawlSite(); // benchmark warmup as a workaround for https://github.com/dotnet/BenchmarkDotNet/issues/837
} |
@adamsitnik , yep, that seems to be exactly the problem! That issue you linked to is an interesting read about how it happens with workload jitting etc taking a long time. I've applied the fix you mentioned though it will be cool to see the change that fixes the core problem land in a later version of BDN. Thanks! |
@adamsitnik, same result than @Turnerj. Before:
After:
Thanks! |
Hey all, with the advent of tiered compilation, it seems like the workaround to this doesn't work anymore. Is there any news on a more solid fix? |
BDN Version: 0.11.3
For a web crawler library I am working on, I am benchmarking my crawler as it crawls a site. The site is a super simple ASP.NET Core site running in-memory via
TestServer
(Microsoft.AspNetCore.TestHost
package).For some reason, when I do requests requests via a dummy
HttpClient
that theTestServer
makes, the ops/iteration count no longer scales in BDN. To make sure I didn't have something else misconfigured, I tried benchmarkingThread.Sleep(2)
andawait Task.Delay(2)
and they definitely scale up the operations.I even tried a non-dummy
HttpClient
to a real website of mine and that also scaled up the operations.While
TestServer
obviously has nothing to do with BDN, it seems strange for this to happen - like it somehow interferes with BDN and the invocation count even though the operations are super fast.I have tried explicitly setting the "invocationCount" when adding the
SimpleJob
attribute to the class and that does make the "ops" but then ends up doing 100 "jobs" (I don't know the terminology) of 128 ops.I assume I can probably keep tweaking settings so it doesn't do that but I want to understand why I even need to set these settings when I haven't needed to for other times I have used BDN.
Here is the actual benchmark:
If you want to run it yourself, you can find the full code on this branch: https://github.com/TurnerSoftware/InfinityCrawler/tree/benchmarking
The benchmark will automatically setup the site and have it running etc - no other work required than just running it. Just for clarity, the same site the benchmarking uses is what my CI tests use and it works fine.
Here is a snippet from the log (Core or CLR, it happens in both):
I know this is more along the lines of either debugging my code or another third-party library than BDN but I don't get why the ops aren't going up automatically. How exactly are the invocation counts determined? Could an invoked method interfere with this besides taking a very long time to load (which my benchmarks aren't as you can see above)? Is it some threading/locking condition that BDN may have issues with so doesn't exceed 1 op?
I guess one other important question: Does it matter that the invocation count isn't scaling when benchmarking? (Cause I have no idea)
Any clarity you can provide would be much appreciated!
The text was updated successfully, but these errors were encountered: