diff --git a/.gitignore b/.gitignore
index fda195ab..2b35ae1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ bin
obj
out/
.idea
+/BenchmarkDotNet.Artifacts
diff --git a/run-benchmark.ps1 b/run-benchmark.ps1
new file mode 100644
index 00000000..0d4430fc
--- /dev/null
+++ b/run-benchmark.ps1
@@ -0,0 +1,15 @@
+param(
+ [ValidateSet('CommandBenchmark','LargeFetchBenchmark')]
+ $Benchmark = 'CommandBenchmark'
+)
+
+$ErrorActionPreference = 'Stop'
+
+$projectFile = '.\src\FirebirdSql.Data.FirebirdClient.Benchmarks\FirebirdSql.Data.FirebirdClient.Benchmarks.csproj'
+
+# Run selected benchmark
+dotnet run `
+ --project $projectFile `
+ --configuration 'Release' `
+ -- `
+ --filter "*$($Benchmark)*"
diff --git a/src/Perf/CommandBenchmark.Execute.cs b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Execute.cs
similarity index 54%
rename from src/Perf/CommandBenchmark.Execute.cs
rename to src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Execute.cs
index ea05f6d3..606e292f 100644
--- a/src/Perf/CommandBenchmark.Execute.cs
+++ b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Execute.cs
@@ -16,44 +16,40 @@
//$Authors = Jiri Cincura (jiri@cincura.net)
using BenchmarkDotNet.Attributes;
-using FirebirdSql.Data.FirebirdClient;
-namespace Perf;
+namespace FirebirdSql.Data.FirebirdClient.Benchmarks;
-partial class CommandBenchmark
+public partial class CommandBenchmark
{
[GlobalSetup(Target = nameof(Execute))]
public void ExecuteGlobalSetup()
{
- GlobalSetupBase();
- using (var conn = new FbConnection(ConnectionString))
- {
- conn.Open();
- using (var cmd = conn.CreateCommand())
- {
- cmd.CommandText = $"create table foobar (x {DataType})";
- cmd.ExecuteNonQuery();
- }
- }
+ CreateDatabase();
+
+ using var conn = new FbConnection(ConnectionString);
+ conn.Open();
+
+ using var cmd = conn.CreateCommand();
+ cmd.CommandText = $"CREATE TABLE foobar (x {DataType})";
+ cmd.ExecuteNonQuery();
}
[Benchmark]
public void Execute()
{
- using (var conn = new FbConnection(ConnectionString))
+ using var conn = new FbConnection(ConnectionString);
+ conn.Open();
+
+ using var cmd = conn.CreateCommand();
+ cmd.CommandText = @"INSERT INTO foobar (x) VALUES (@cnt)";
+
+ var p = new FbParameter() { ParameterName = "@cnt" };
+ cmd.Parameters.Add(p);
+
+ for (var i = 0; i < Count; i++)
{
- conn.Open();
- using (var cmd = conn.CreateCommand())
- {
- cmd.CommandText = @"insert into foobar values (@cnt)";
- var p = new FbParameter() { ParameterName = "@cnt" };
- cmd.Parameters.Add(p);
- for (var i = 0; i < Count; i++)
- {
- p.Value = i;
- cmd.ExecuteNonQuery();
- }
- }
+ p.Value = i;
+ cmd.ExecuteNonQuery();
}
}
}
diff --git a/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Fetch.cs b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Fetch.cs
new file mode 100644
index 00000000..bff88363
--- /dev/null
+++ b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.Fetch.cs
@@ -0,0 +1,71 @@
+/*
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * https://github.com/FirebirdSQL/NETProvider/raw/master/license.txt.
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * All Rights Reserved.
+ */
+
+//$Authors = Jiri Cincura (jiri@cincura.net)
+
+using BenchmarkDotNet.Attributes;
+
+namespace FirebirdSql.Data.FirebirdClient.Benchmarks;
+
+public partial class CommandBenchmark
+{
+ [GlobalSetup(Target = nameof(Fetch))]
+ public void FetchGlobalSetup()
+ {
+ CreateDatabase();
+
+ using var conn = new FbConnection(ConnectionString);
+ conn.Open();
+
+ using (var cmd = conn.CreateCommand())
+ {
+ cmd.CommandText = $"CREATE TABLE foobar (x {DataType})";
+ cmd.ExecuteNonQuery();
+ }
+
+ using (var cmd = conn.CreateCommand())
+ {
+ cmd.CommandText = $"""
+ EXECUTE BLOCK AS
+ DECLARE cnt INT;
+ BEGIN
+ cnt = {Count};
+ WHILE (cnt > 0) DO
+ BEGIN
+ INSERT INTO foobar VALUES (:cnt);
+ cnt = cnt - 1;
+ END
+ END
+ """;
+ cmd.ExecuteNonQuery();
+ }
+ }
+
+ [Benchmark]
+ public void Fetch()
+ {
+ using var conn = new FbConnection(ConnectionString);
+ conn.Open();
+
+ using var cmd = conn.CreateCommand();
+ cmd.CommandText = "SELECT x FROM foobar";
+
+ using var reader = cmd.ExecuteReader();
+ while (reader.Read())
+ {
+ var _ = reader[0];
+ }
+ }
+}
diff --git a/src/Perf/CommandBenchmark.cs b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.cs
similarity index 70%
rename from src/Perf/CommandBenchmark.cs
rename to src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.cs
index b6a02f11..881dbd03 100644
--- a/src/Perf/CommandBenchmark.cs
+++ b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/CommandBenchmark.cs
@@ -21,9 +21,9 @@
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains.CsProj;
-using FirebirdSql.Data.FirebirdClient;
+using BenchmarkDotNet.Validators;
-namespace Perf;
+namespace FirebirdSql.Data.FirebirdClient.Benchmarks;
[Config(typeof(Config))]
public partial class CommandBenchmark
@@ -34,30 +34,46 @@ public Config()
{
var baseJob = Job.Default
.WithWarmupCount(3)
- .WithToolchain(CsProjCoreToolchain.NetCoreApp60)
.WithPlatform(Platform.X64)
.WithJit(Jit.RyuJit);
+
+ AddJob(
+ baseJob
+ .WithToolchain(CsProjCoreToolchain.NetCoreApp80)
+ .WithCustomBuildConfiguration("ReleaseNuGet")
+ .WithId("NuGet80")
+ .AsBaseline()
+ );
+
+ AddJob(
+ baseJob
+ .WithToolchain(CsProjCoreToolchain.NetCoreApp80)
+ .WithCustomBuildConfiguration("Release")
+ .WithId("Core80")
+ );
+
AddDiagnoser(MemoryDiagnoser.Default);
- AddJob(baseJob.WithCustomBuildConfiguration("Release").WithId("Project"));
- AddJob(baseJob.WithCustomBuildConfiguration("ReleaseNuGet").WithId("NuGet").AsBaseline());
+
+ AddValidator(BaselineValidator.FailOnError);
+ AddValidator(JitOptimizationsValidator.FailOnError);
}
}
protected const string ConnectionString = "database=localhost:benchmark.fdb;user=sysdba;password=masterkey";
- [Params("bigint", "varchar(10) character set utf8")]
+ [Params("BIGINT", "VARCHAR(10) CHARACTER SET UTF8")]
public string DataType { get; set; }
[Params(100)]
public int Count { get; set; }
- void GlobalSetupBase()
+ static void CreateDatabase()
{
FbConnection.CreateDatabase(ConnectionString, 16 * 1024, false, true);
}
[GlobalCleanup]
- public void GlobalCleanup()
+ public static void GlobalCleanup()
{
FbConnection.ClearAllPools();
FbConnection.DropDatabase(ConnectionString);
diff --git a/src/Perf/Perf.csproj b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/FirebirdSql.Data.FirebirdClient.Benchmarks.csproj
similarity index 97%
rename from src/Perf/Perf.csproj
rename to src/FirebirdSql.Data.FirebirdClient.Benchmarks/FirebirdSql.Data.FirebirdClient.Benchmarks.csproj
index f47a017c..ab9f8e79 100644
--- a/src/Perf/Perf.csproj
+++ b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/FirebirdSql.Data.FirebirdClient.Benchmarks.csproj
@@ -19,6 +19,6 @@
-
+
diff --git a/src/Perf/Program.cs b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/Program.cs
similarity index 81%
rename from src/Perf/Program.cs
rename to src/FirebirdSql.Data.FirebirdClient.Benchmarks/Program.cs
index 484f5634..dbb557d7 100644
--- a/src/Perf/Program.cs
+++ b/src/FirebirdSql.Data.FirebirdClient.Benchmarks/Program.cs
@@ -15,15 +15,8 @@
//$Authors = Jiri Cincura (jiri@cincura.net)
-using System.Reflection;
using BenchmarkDotNet.Running;
-namespace Perf;
-
-class Program
-{
- static void Main(string[] args)
- {
- BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
- }
-}
+BenchmarkSwitcher
+ .FromAssembly(typeof(Program).Assembly)
+ .Run(args);
diff --git a/src/FirebirdSql.Data.FirebirdClient.Tests/FbTransactionTests.cs b/src/FirebirdSql.Data.FirebirdClient.Tests/FbTransactionTests.cs
index d3a7d990..144375b7 100644
--- a/src/FirebirdSql.Data.FirebirdClient.Tests/FbTransactionTests.cs
+++ b/src/FirebirdSql.Data.FirebirdClient.Tests/FbTransactionTests.cs
@@ -139,4 +139,22 @@ public async Task SnapshotAtNumber()
}
}
}
+
+ [Test]
+ public async Task CanGetTransactionId()
+ {
+ if (!EnsureServerVersionAtLeast(new Version(2, 5, 0, 0)))
+ return;
+
+ await using (var transaction1 = await Connection.BeginTransactionAsync())
+ {
+ var idFromInfo = await new FbTransactionInfo(transaction1).GetTransactionIdAsync();
+ Assert.NotZero(idFromInfo);
+
+ var command = new FbCommand("SELECT current_transaction FROM rdb$database", Connection, transaction1);
+ var idFromSql = await command.ExecuteScalarAsync();
+
+ Assert.AreEqual(idFromInfo, idFromSql);
+ }
+ }
}
diff --git a/src/FirebirdSql.Data.FirebirdClient/Common/IscHelper.cs b/src/FirebirdSql.Data.FirebirdClient/Common/IscHelper.cs
index 578895f7..3cf67ac7 100644
--- a/src/FirebirdSql.Data.FirebirdClient/Common/IscHelper.cs
+++ b/src/FirebirdSql.Data.FirebirdClient/Common/IscHelper.cs
@@ -206,6 +206,10 @@ public static List