Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0" PrivateAssets="all" />

</ItemGroup>

<ItemGroup>
<Folder Include="Model\CompiledModel\" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// <auto-generated />
using Benchmarks;
using Benchmarks.Model;
using Microsoft.EntityFrameworkCore.Infrastructure;

#pragma warning disable 219, 612, 618
#nullable disable

[assembly: DbContextModel(typeof(DatabaseContext), typeof(DatabaseContextModel))]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// <auto-generated />
using Benchmarks.Model;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Benchmarks
{
[DbContext(typeof(DatabaseContext))]
public partial class DatabaseContextModel : RuntimeModel
{
private static readonly bool _useOldBehavior31751 =
System.AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31751", out var enabled31751) && enabled31751;

static DatabaseContextModel()
{
var model = new DatabaseContextModel();

if (_useOldBehavior31751)
{
model.Initialize();
}
else
{
var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024);
thread.Start();
thread.Join();

void RunInitialization()
{
model.Initialize();
}
}

model.Customize();
_instance = (DatabaseContextModel)model.FinalizeModel();
}

private static DatabaseContextModel _instance;
public static IModel Instance => _instance;

partial void Initialize();

partial void Customize();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Benchmarks
{
public partial class DatabaseContextModel
{
private DatabaseContextModel()
: base(skipDetectChanges: false, modelId: new Guid("e6a922c5-5e25-4191-8617-6c6410b754cc"), entityTypeCount: 2)
{
}

partial void Initialize()
{
var fortune = FortuneEntityType.Create(this);
var world = WorldEntityType.Create(this);

FortuneEntityType.CreateAnnotations(fortune);
WorldEntityType.CreateAnnotations(world);

AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
AddAnnotation("ProductVersion", "10.0.0");
AddAnnotation("Relational:MaxIdentifierLength", 63);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// <auto-generated />
using System;
using System.Reflection;
using Benchmarks.Model;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Benchmarks
{
[EntityFrameworkInternal]
public partial class FortuneEntityType
{
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
{
var runtimeEntityType = model.AddEntityType(
"Benchmarks.Model.Fortune",
typeof(Fortune),
baseEntityType,
propertyCount: 2,
keyCount: 1);

var id = runtimeEntityType.AddProperty(
"Id",
typeof(int),
propertyInfo: typeof(Fortune).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(Fortune).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
valueGenerated: ValueGenerated.OnAdd,
afterSaveBehavior: PropertySaveBehavior.Throw,
sentinel: 0);
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
id.AddAnnotation("Relational:ColumnName", "id");

var message = runtimeEntityType.AddProperty(
"Message",
typeof(string),
propertyInfo: typeof(Fortune).GetProperty("Message", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(Fortune).GetField("<Message>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
nullable: true,
maxLength: 2048);
message.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
message.AddAnnotation("Relational:ColumnName", "message");

var key = runtimeEntityType.AddKey(
new[] { id });
runtimeEntityType.SetPrimaryKey(key);

return runtimeEntityType;
}

public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
{
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
runtimeEntityType.AddAnnotation("Relational:Schema", null);
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
runtimeEntityType.AddAnnotation("Relational:TableName", "fortune");
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);

Customize(runtimeEntityType);
}

static partial void Customize(RuntimeEntityType runtimeEntityType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// <auto-generated />
using System;
using System.Reflection;
using Benchmarks.Model;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

#pragma warning disable 219, 612, 618
#nullable disable

namespace Benchmarks
{
[EntityFrameworkInternal]
public partial class WorldEntityType
{
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
{
var runtimeEntityType = model.AddEntityType(
"Benchmarks.Model.World",
typeof(World),
baseEntityType,
propertyCount: 2,
keyCount: 1);

var id = runtimeEntityType.AddProperty(
"Id",
typeof(int),
propertyInfo: typeof(World).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(World).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
valueGenerated: ValueGenerated.OnAdd,
afterSaveBehavior: PropertySaveBehavior.Throw,
sentinel: 0);
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
id.AddAnnotation("Relational:ColumnName", "id");

var randomNumber = runtimeEntityType.AddProperty(
"RandomNumber",
typeof(int),
propertyInfo: typeof(World).GetProperty("RandomNumber", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
fieldInfo: typeof(World).GetField("<RandomNumber>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
sentinel: 0);
randomNumber.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
randomNumber.AddAnnotation("Relational:ColumnName", "randomnumber");

var key = runtimeEntityType.AddKey(
new[] { id });
runtimeEntityType.SetPrimaryKey(key);

return runtimeEntityType;
}

public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
{
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
runtimeEntityType.AddAnnotation("Relational:Schema", null);
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
runtimeEntityType.AddAnnotation("Relational:TableName", "world");
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);

Customize(runtimeEntityType);
}

static partial void Customize(RuntimeEntityType runtimeEntityType);
}
}
15 changes: 15 additions & 0 deletions frameworks/CSharp/genhttp/Benchmarks/Model/Database.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Benchmarks.Model;

public static class Database
{
public static readonly DatabaseContextPool<DatabaseContext> NoTrackingPool;

public static readonly DatabaseContextPool<DatabaseContext> TrackingPool;

static Database()
{
NoTrackingPool = new DatabaseContextPool<DatabaseContext>(factory: DatabaseContext.CreateNoTracking, maxSize: 512);
TrackingPool = new DatabaseContextPool<DatabaseContext>(factory: DatabaseContext.CreateTracking, maxSize: 512);
}

}
41 changes: 23 additions & 18 deletions frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace Benchmarks.Model;

public sealed class DatabaseContext : DbContext
{
private static DbContextOptions<DatabaseContext> _options;
private static readonly Lazy<DbContextOptions<DatabaseContext>> TrackingOptions = new(() => CreateOptions(true), LazyThreadSafetyMode.ExecutionAndPublication);

private static DbContextOptions<DatabaseContext> _noTrackingOptions;
private static readonly Lazy<DbContextOptions<DatabaseContext>> NoTrackingOptions = new(() => CreateOptions(false), LazyThreadSafetyMode.ExecutionAndPublication);

#region Factory
public static DatabaseContext CreateTracking() => new(TrackingOptions.Value, true);

public static DatabaseContext Create() => new(_options ??= GetOptions(true));
public static DatabaseContext CreateNoTracking() => new(NoTrackingOptions.Value, false);

public static DatabaseContext CreateNoTracking() => new(_noTrackingOptions ??= GetOptions(false));

private static DbContextOptions<DatabaseContext> GetOptions(bool tracking)
private static DbContextOptions<DatabaseContext> CreateOptions(bool tracking)
{
var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
var services = new ServiceCollection();

services.AddEntityFrameworkNpgsql();

var provider = services.BuildServiceProvider();

optionsBuilder.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4");
var builder = new DbContextOptionsBuilder<DatabaseContext>();

builder.UseInternalServiceProvider(provider)
.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true")
.EnableThreadSafetyChecks(false)
.UseModel(DatabaseContextModel.Instance);

if (!tracking)
{
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}

return optionsBuilder.Options;
return builder.Options;
}

private DatabaseContext(DbContextOptions options) : base(options) { }

#endregion

#region Entities
internal DatabaseContext(DbContextOptions<DatabaseContext> options, bool tracking = false) : base(options)
{
ChangeTracker.AutoDetectChangesEnabled = tracking;
}

public DbSet<World> World { get; set; }

public DbSet<Fortune> Fortune { get; set; }

#endregion

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Benchmarks.Model;

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

public class DatabaseContextFactory : IDesignTimeDbContextFactory<DatabaseContext>
{

public DatabaseContext CreateDbContext(string[] args)
{
var options = new DbContextOptionsBuilder<DatabaseContext>()
.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable")
.Options;

return new DatabaseContext(options);
}

}
46 changes: 46 additions & 0 deletions frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContextPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace Benchmarks.Model;

using System.Collections.Concurrent;

using Microsoft.EntityFrameworkCore;

public sealed class DatabaseContextPool<TContext> where TContext : DbContext
{
private readonly ConcurrentBag<TContext> _pool = new();

private readonly Func<TContext> _factory;

private readonly int _maxSize;

public DatabaseContextPool(Func<TContext> factory, int maxSize)
{
_factory = factory;
_maxSize = maxSize;
}

public TContext Rent()
{
if (_pool.TryTake(out var ctx))
{
ctx.ChangeTracker.Clear();
return ctx;
}

return _factory();
}

public void Return(TContext context)
{
if (_pool.Count >= _maxSize)
{
context.Dispose();
return;
}


context.ChangeTracker.Clear();

_pool.Add(context);
}

}
Loading
Loading