Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.IO.Pipelines;
using System.Threading.Tasks;

namespace PlatformBenchmarks
{
public partial class BenchmarkApplication
{
private async Task Caching(PipeWriter pipeWriter, int count)
{
OutputMultipleQueries(pipeWriter, await Db.LoadCachedQueries(count));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.IO.Pipelines;
using System.Text.Encodings.Web;
using System.Threading.Tasks;

namespace PlatformBenchmarks
{
public partial class BenchmarkApplication
{
private readonly static AsciiString _fortunesPreamble =
_http11OK +
_headerServer + _crlf +
_headerContentTypeHtml + _crlf +
_headerContentLength;

private async Task Fortunes(PipeWriter pipeWriter)
{
OutputFortunes(pipeWriter, await Db.LoadFortunesRows());
}

private void OutputFortunes(PipeWriter pipeWriter, List<Fortune> model)
{
var writer = GetWriter(pipeWriter, sizeHint: 1600); // in reality it's 1361

writer.Write(_fortunesPreamble);

var lengthWriter = writer;
writer.Write(_contentLengthGap);

// Date header
writer.Write(DateHeader.HeaderBytes);

var bodyStart = writer.Buffered;
// Body
writer.Write(_fortunesTableStart);
foreach (var item in model)
{
writer.Write(_fortunesRowStart);
writer.WriteNumeric((uint)item.Id);
writer.Write(_fortunesColumn);
writer.WriteUtf8String(HtmlEncoder.Encode(item.Message));
writer.Write(_fortunesRowEnd);
}
writer.Write(_fortunesTableEnd);
lengthWriter.WriteNumeric((uint)(writer.Buffered - bodyStart));

writer.Commit();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Buffers;
using System.IO.Pipelines;
using System.Threading.Tasks;
using Utf8Json;

namespace PlatformBenchmarks
{
public partial class BenchmarkApplication
{
private async Task MultipleQueries(PipeWriter pipeWriter, int count)
{
OutputMultipleQueries(pipeWriter, await Db.LoadMultipleQueriesRows(count));
}

private static void OutputMultipleQueries(PipeWriter pipeWriter, World[] rows)
{
var writer = GetWriter(pipeWriter, sizeHint: 160 * rows.Length); // in reality it's 152 for one

writer.Write(_dbPreamble);

var lengthWriter = writer;
writer.Write(_contentLengthGap);

// Date header
writer.Write(DateHeader.HeaderBytes);

writer.Commit();

var jsonPayload = JsonSerializer.SerializeUnsafe(rows);
pipeWriter.Write(jsonPayload);

// Content-Length
lengthWriter.WriteNumeric((uint)jsonPayload.Count);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Buffers;
using System.IO.Pipelines;
using System.Threading.Tasks;
using Utf8Json;

namespace PlatformBenchmarks
{
public partial class BenchmarkApplication
{
private async Task SingleQuery(PipeWriter pipeWriter)
{
OutputSingleQuery(pipeWriter, await Db.LoadSingleQueryRow());
}

private static void OutputSingleQuery(PipeWriter pipeWriter, World row)
{
var writer = GetWriter(pipeWriter, sizeHint: 180); // in reality it's 150

writer.Write(_dbPreamble);

var lengthWriter = writer;
writer.Write(_contentLengthGap);

// Date header
writer.Write(DateHeader.HeaderBytes);

writer.Commit();

var jsonPayload = JsonSerializer.SerializeUnsafe(row);
pipeWriter.Write(jsonPayload);

// Content-Length
lengthWriter.WriteNumeric((uint)jsonPayload.Count);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Buffers;
using System.IO.Pipelines;
using System.Threading.Tasks;
using Utf8Json;

namespace PlatformBenchmarks
{
public partial class BenchmarkApplication
{
private async Task Updates(PipeWriter pipeWriter, int count)
{
OutputUpdates(pipeWriter, await Db.LoadMultipleUpdatesRows(count));
}

private static void OutputUpdates(PipeWriter pipeWriter, World[] rows)
{
var writer = GetWriter(pipeWriter, sizeHint: 120 * rows.Length); // in reality it's 112 for one

writer.Write(_dbPreamble);

var lengthWriter = writer;
writer.Write(_contentLengthGap);

// Date header
writer.Write(DateHeader.HeaderBytes);

writer.Commit();

var jsonPayload = JsonSerializer.SerializeUnsafe(rows);
pipeWriter.Write(jsonPayload);

// Content-Length
lengthWriter.WriteNumeric((uint)jsonPayload.Count);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ public partial class BenchmarkApplication
private readonly static AsciiString _fortunesTableEnd = "</table></body></html>";
private readonly static AsciiString _contentLengthGap = new string(' ', 4);

#if DATABASE
public static RawDb Db { get; set; }
#endif

[ThreadStatic]
private static Utf8JsonWriter t_writer;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace PlatformBenchmarks
{
public class AppSettings
{
public string ConnectionString { get; set; }

public DatabaseServer Database { get; set; } = DatabaseServer.None;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace PlatformBenchmarks
{
public enum DatabaseServer
{
None,
SqlServer,
PostgreSql,
MySql
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Linq;

namespace PlatformBenchmarks
{
internal class BatchUpdateString
{
private const int MaxBatch = 500;

public static DatabaseServer DatabaseServer;

internal static readonly string[] Ids = Enumerable.Range(0, MaxBatch).Select(i => $"@Id_{i}").ToArray();
internal static readonly string[] Randoms = Enumerable.Range(0, MaxBatch).Select(i => $"@Random_{i}").ToArray();

private static string[] _queries = new string[MaxBatch + 1];

public static string Query(int batchSize)
{
if (_queries[batchSize] != null)
{
return _queries[batchSize];
}

var lastIndex = batchSize - 1;

var sb = StringBuilderCache.Acquire();

if (DatabaseServer == DatabaseServer.PostgreSql)
{
sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@Id_{i}, @Random_{i}), "));
sb.Append($"(@Id_{lastIndex}, @Random_{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
}
else
{
Enumerable.Range(0, batchSize).ToList().ForEach(i => sb.Append($"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};"));
}

return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Runtime.InteropServices;

namespace PlatformBenchmarks
{
public class CachedWorld
{
public int Id { get; set; }

public int RandomNumber { get; set; }

public static implicit operator World(CachedWorld world) => new World { Id = world.Id, RandomNumber = world.RandomNumber };
public static implicit operator CachedWorld(World world) => new CachedWorld { Id = world.Id, RandomNumber = world.RandomNumber };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;

namespace PlatformBenchmarks
{
public readonly struct Fortune : IComparable<Fortune>, IComparable
{
public Fortune(int id, string message)
{
Id = id;
Message = message;
}

public int Id { get; }

public string Message { get; }

public int CompareTo(object obj) => throw new InvalidOperationException("The non-generic CompareTo should not be used");

// Performance critical, using culture insensitive comparison
public int CompareTo(Fortune other) => string.CompareOrdinal(Message, other.Message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Runtime.CompilerServices;
using System.Threading;

namespace PlatformBenchmarks
{
public class ConcurrentRandom
{
private static int nextSeed = 0;

// Random isn't thread safe
[ThreadStatic]
private static Random _random;

private static Random Random => _random ?? CreateRandom();

[MethodImpl(MethodImplOptions.NoInlining)]
private static Random CreateRandom()
{
_random = new Random(Interlocked.Increment(ref nextSeed));
return _random;
}

public int Next(int minValue, int maxValue)
{
return Random.Next(minValue, maxValue);
}
}
}
Loading