|
@@ -2,7 +2,6 @@
|
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
|
|
using System;
|
|
|
-using System.Collections.Concurrent;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Runtime.CompilerServices;
|
|
@@ -14,9 +13,6 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
public class RawDb
|
|
|
{
|
|
|
- private static readonly ConcurrentQueue<SqlReadCommand> _sqlReadCommands = new ConcurrentQueue<SqlReadCommand>();
|
|
|
- private static readonly ConcurrentQueue<SqlFortuneCommand> _sqlFortuneCommands = new ConcurrentQueue<SqlFortuneCommand>();
|
|
|
- private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
|
|
|
private readonly ConcurrentRandom _random;
|
|
|
private readonly string _connectionString;
|
|
|
private readonly MemoryCache _cache = new MemoryCache(
|
|
@@ -37,10 +33,9 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using (var cmd = CreateReadCommand())
|
|
|
+ var (cmd, _) = CreateReadCommand(db);
|
|
|
+ using (cmd)
|
|
|
{
|
|
|
- cmd.Connection = db;
|
|
|
- cmd.Parameter.TypedValue = _random.Next(0, 10000) + 1;
|
|
|
return await ReadSingleRow(cmd);
|
|
|
}
|
|
|
}
|
|
@@ -54,14 +49,13 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using (var cmd = CreateReadCommand())
|
|
|
+ var (cmd, idParameter) = CreateReadCommand(db);
|
|
|
+ using (cmd)
|
|
|
{
|
|
|
- cmd.Connection = db;
|
|
|
- var param = cmd.Parameter;
|
|
|
for (int i = 0; i < result.Length; i++)
|
|
|
{
|
|
|
- param.TypedValue = _random.Next(0, 10000) + 1;
|
|
|
result[i] = await ReadSingleRow(cmd);
|
|
|
+ idParameter.TypedValue = _random.Next(1, 10001);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -99,9 +93,9 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using (var cmd = CreateReadCommand())
|
|
|
+ var (cmd, idParameter) = rawdb.CreateReadCommand(db);
|
|
|
+ using (cmd)
|
|
|
{
|
|
|
- cmd.Connection = db;
|
|
|
Func<ICacheEntry, Task<CachedWorld>> create = async (entry) =>
|
|
|
{
|
|
|
return await rawdb.ReadSingleRow(cmd);
|
|
@@ -110,8 +104,7 @@ namespace PlatformBenchmarks
|
|
|
var cacheKeys = _cacheKeys;
|
|
|
var key = cacheKeys[id];
|
|
|
|
|
|
- var param = cmd.Parameter;
|
|
|
- param.TypedValue = id;
|
|
|
+ idParameter.TypedValue = id;
|
|
|
|
|
|
for (; i < result.Length; i++)
|
|
|
{
|
|
@@ -119,7 +112,7 @@ namespace PlatformBenchmarks
|
|
|
result[i] = data;
|
|
|
|
|
|
id = rawdb._random.Next(1, 10001);
|
|
|
- param.TypedValue = id;
|
|
|
+ idParameter.TypedValue = id;
|
|
|
key = cacheKeys[id];
|
|
|
}
|
|
|
}
|
|
@@ -135,14 +128,14 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using (var cmd = CreateReadCommand())
|
|
|
+ var (cmd, idParameter) = CreateReadCommand(db);
|
|
|
+ using (cmd)
|
|
|
{
|
|
|
- cmd.Connection = db;
|
|
|
var cacheKeys = _cacheKeys;
|
|
|
var cache = _cache;
|
|
|
for (var i = 1; i < 10001; i++)
|
|
|
{
|
|
|
- cmd.Parameter.TypedValue = i;
|
|
|
+ idParameter.TypedValue = i;
|
|
|
cache.Set<CachedWorld>(cacheKeys[i], await ReadSingleRow(cmd));
|
|
|
}
|
|
|
}
|
|
@@ -159,14 +152,13 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using (var cmd = CreateReadCommand())
|
|
|
+ var (queryCmd, queryParameter) = CreateReadCommand(db);
|
|
|
+ using (queryCmd)
|
|
|
{
|
|
|
- cmd.Connection = db;
|
|
|
- var queryParameter = cmd.Parameter;
|
|
|
for (int i = 0; i < results.Length; i++)
|
|
|
{
|
|
|
- queryParameter.TypedValue = _random.Next(0, 10000) + 1;
|
|
|
- results[i] = await ReadSingleRow(cmd);
|
|
|
+ results[i] = await ReadSingleRow(queryCmd);
|
|
|
+ queryParameter.TypedValue = _random.Next(1, 10001);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -200,9 +192,7 @@ namespace PlatformBenchmarks
|
|
|
{
|
|
|
await db.OpenAsync();
|
|
|
|
|
|
- using var cmd = CreateFortuneCommand();
|
|
|
- cmd.Connection = db;
|
|
|
-
|
|
|
+ using (var cmd = new NpgsqlCommand("SELECT id, message FROM fortune", db))
|
|
|
using (var rdr = await cmd.ExecuteReaderAsync())
|
|
|
{
|
|
|
while (await rdr.ReadAsync())
|
|
@@ -222,24 +212,14 @@ namespace PlatformBenchmarks
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- private static SqlReadCommand CreateReadCommand()
|
|
|
+ private (NpgsqlCommand readCmd, NpgsqlParameter<int> idParameter) CreateReadCommand(NpgsqlConnection connection)
|
|
|
{
|
|
|
- if (!_sqlReadCommands.TryDequeue(out var cmd))
|
|
|
- {
|
|
|
- cmd = new SqlReadCommand();
|
|
|
- }
|
|
|
+ var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id", connection);
|
|
|
+ var parameter = new NpgsqlParameter<int>(parameterName: "@Id", value: _random.Next(1, 10001));
|
|
|
|
|
|
- return cmd;
|
|
|
- }
|
|
|
-
|
|
|
- private static SqlFortuneCommand CreateFortuneCommand()
|
|
|
- {
|
|
|
- if (!_sqlFortuneCommands.TryDequeue(out var cmd))
|
|
|
- {
|
|
|
- cmd = new SqlFortuneCommand();
|
|
|
- }
|
|
|
+ cmd.Parameters.Add(parameter);
|
|
|
|
|
|
- return cmd;
|
|
|
+ return (cmd, parameter);
|
|
|
}
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
@@ -257,55 +237,7 @@ namespace PlatformBenchmarks
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- internal class SqlFortuneCommand : IDisposable
|
|
|
- {
|
|
|
- private readonly NpgsqlCommand _cmd;
|
|
|
-
|
|
|
- public NpgsqlConnection Connection
|
|
|
- {
|
|
|
- set { _cmd.Connection = value; }
|
|
|
- }
|
|
|
-
|
|
|
- public SqlFortuneCommand()
|
|
|
- {
|
|
|
- _cmd = new NpgsqlCommand("SELECT id, message FROM fortune");
|
|
|
- }
|
|
|
-
|
|
|
- public Task<NpgsqlDataReader> ExecuteReaderAsync() => _cmd.ExecuteReaderAsync();
|
|
|
-
|
|
|
- public void Dispose()
|
|
|
- {
|
|
|
- _cmd.Connection = null;
|
|
|
- _sqlFortuneCommands.Enqueue(this);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- internal class SqlReadCommand : IDisposable
|
|
|
- {
|
|
|
- private readonly NpgsqlCommand _cmd;
|
|
|
- private readonly NpgsqlParameter<int> _parameter;
|
|
|
-
|
|
|
- public NpgsqlParameter<int> Parameter => _parameter;
|
|
|
- public NpgsqlConnection Connection
|
|
|
- {
|
|
|
- set { _cmd.Connection = value; }
|
|
|
- }
|
|
|
-
|
|
|
- public SqlReadCommand()
|
|
|
- {
|
|
|
- _cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id");
|
|
|
- _parameter = new NpgsqlParameter<int>(parameterName: "@Id", value: 0);
|
|
|
- _cmd.Parameters.Add(_parameter);
|
|
|
- }
|
|
|
-
|
|
|
- public static implicit operator NpgsqlCommand(SqlReadCommand c) => c._cmd;
|
|
|
-
|
|
|
- public void Dispose()
|
|
|
- {
|
|
|
- _cmd.Connection = null;
|
|
|
- _sqlReadCommands.Enqueue(this);
|
|
|
- }
|
|
|
- }
|
|
|
+ private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
|
|
|
|
|
|
public sealed class CacheKey : IEquatable<CacheKey>
|
|
|
{
|