BenchmarkDotNet in LinqPad

Hi all,
I'm just not able to move forward with BenchmarkDotNet in LinqPad.

Basically I have same problem as tym32167 on his github issue :
https://github.com/dotnet/BenchmarkDotNet/issues/593#issue-276705515

// Validating benchmarks:
Assembly LINQPadQuery, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is located in temp. If you are running benchmarks from xUnit you need to disable shadow copy. It's not supported by design.
I'm trying to run a sample from benchmarkdotnet issue 580

https://github.com/dotnet/BenchmarkDotNet/issues/580

void Main()
{
	var summary = BenchmarkRunner.Run<Md5VsSha256>();
}

public class Md5VsSha256
{
	private const int N = 10000;
	private readonly byte[] data;

	private readonly SHA256 sha256 = SHA256.Create();
	private readonly MD5 md5 = MD5.Create();

	public Md5VsSha256()
	{
		data = new byte[N];
		new Random(42).NextBytes(data);
	}

	[Benchmark]
	public byte[] Sha256() => sha256.ComputeHash(data);

	[Benchmark]
	public byte[] Md5() => md5.ComputeHash(data);
}

Adam Sitnik is saying that the issue was solved, but it doesn't work.

BenchmarkDotNet version 0.11.5.1095 (their CI nuget server)
LinqPad version 5.39.00
Roslyn Preview > Use experimental Roslyn assemblies. (but checking or unchecking this doesn't make any difference)

Compiler optimization on (/o+)
Do not shadow assembly reference True.

I kindly ask you to any how-to, if there's any.
Thanks.

Comments

  • edited June 11
    From what I can see in the comments, Benchmark.net is .NET Core-only, so it won't work with LINQPad 5. FWIW, I don't believe it will work with LINQPad 6 either, because I think it expects a .csproj file. So it's Visual Studio only.

    It's quite possible that LINQPad 6 will end up with a built-in benchmarking utility of some sort. If it did, what kind of features would you need?
  • Hi Joe !

    First of all, I have to appologize, actually I'm able to run the sample benchmark.
    Yesterday I had to mix up some code and it look like not running.
    Today I made a sample from scratch.
    The line Assembly LINQPadQuery, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is located in temp. is still in the output, but actually the benchmark is running.

    I'm bit confused by your answer, Benchmark.net is available also for full .net framework.
    https://benchmarkdotnet.org/articles/overview.html

    I was able to run sample benchmark (from the example above) in .net core 2.1.11 and full .Net Framework 4.7.2.
    It also doesn't expect csproj file. You can create console application and run it.

    To answer your question regarding benchmarking features. I can use benchmarkdotnet in LinqPad (well, mostly, see below) and I don't necessarily need special LinqPad benchmarking features.

    They also made special logger for LinqPad. (PR 903 and PR 915)
    https://github.com/dotnet/BenchmarkDotNet/pulls?q=is:pr+linqpad+is:closed

    That left me with thinking, that there is maybe problem somewhere else.
    And indeed my problem is with the generated TypedDataContext.

    Actually I'd like to benchmark FileStream feature of SQL Server.
    I made a table
    CREATE TABLE Test.dbo.Records
    (
        [Id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE, 
        [SerialNumber] INTEGER UNIQUE,
        [Chart] VARBINARY(MAX) FILESTREAM NULL
    )
    and the Benchmark test
    void Main()
    {
    	var summary = BenchmarkRunner.Run<FileStreamTest>();
    }
    
    public class FileStreamTest
    {
    	Random rnd = new Random();
    	
    	[Benchmark]
    	public byte[] ReadFileStream()
    	{
    		return Records.First(x=>x.SerialNumber==rnd.Next(1000)).Chart.ToArray();
    	}
    }
    the problem is that Recordsare not recognized as I would like to.
    With an error
    CS0120 An object reference is required for the non-static field, method, or property 'TypedDataContext.Records'

    This is actually not a problem of Benchmark Dotnet. This problem is shown in any class which tries to access data.
    See example. Method GetFirst of a class AccessFromAclass doesn't work.
    void Main()
    {
    	
    }
    
    public Records GetFirst()
    {
            //success
    	return Records.First();
    }
    
    public class AccessFromAclass
    {
    	public Records GetFirst()
    	{
                    //fails to compile
    		return Records.First();
    	}
    }
    Is there any way how to fix that ?
    Thanks !

    (also probably this thread should be renamed to something like Accessing TypedDataContext from a class)
  • edited June 12
    This is because Customers and Records are instance methods of the data context class. LINQPad subclasses the typed data context that is generated (whether by LINQ to SQL or Entity Framework), and it's a feature of those libraries that Customer and Records have to be instance members. The subclass that LINQPad creates for your query is called UserQuery.

    There are (at least) two ways to work around this. (I can't you which is best in your case, because I've not had any luck in getting Benchmarkdotnet to work at all.)

    The first is to keep it all in the same class:
    void Main()
    {
    	var summary = BenchmarkRunner.Run<UserQuery>();
    }
    
    Random rnd = new Random();
    	
    [Benchmark]
    public byte[] ReadFileStream()
    {
    	return Records.First(x=>x.SerialNumber==rnd.Next(1000)).Chart.ToArray();
    }
    
    The other is to use the static variable Util.CurrentDataContext:
    void Main()
    {
        new MyClass().Foo();
    }
    
    class MyClass
    {
        UserQuery Data => (UserQuery)Util.CurrentDataContext;
        
        public void Foo()
        {
            Data.Customers.Dump();
        }
    }
  • Hi Joe,
    thanks for the info.
    Especially (UserQuery)Util.CurrentDataContext; is good to know !

    For this particular scenario neither approach is good.

    First approach returns
    // Build Error: The build has failed!
    CS7036: There is no argument given that corresponds to the required formal parameter 'connection' of 'UserQuery.UserQuery(IDbConnection)' 
    second returns
    
    // BeforeAnythingElse
    System.NullReferenceException: Object reference not set to an instance of an object.
       at BenchmarkDotNet.Autogenerated.UniqueProgramName.AfterAssemblyLoadingAttached(String[] args)
    But I believe these are already specifics of BenchmarkDotNet.

    I should probably learn more about Util class. Is there any API web page ? Or as I can see, there is already LINQPad Tutorial & Reference folder in Samples area. I should look there as a reference, right ?


Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!