Skip to content

Commit

Permalink
Merge pull request #28 from akkadotnet/dev
Browse files Browse the repository at this point in the history
Akka.Persistence.Linq2Db v1.4.21 Release
  • Loading branch information
Aaronontheweb authored Jul 6, 2021
2 parents e06499a + 644f270 commit 170c39a
Show file tree
Hide file tree
Showing 43 changed files with 535 additions and 303 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<PropertyGroup>
<ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\src\Akka.Persistence.Linq2Db.Benchmark.Tests\Akka.Persistence.Linq2Db.Benchmark.Tests.csproj" />
<ProjectReference Include="..\src\Akka.Persistence.Sql.Linq2Db.DockerTests\Akka.Persistence.Sql.Linq2Db.DockerTests.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Akka.Persistence.Sql.Linq2Db.Tests.Docker;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker.Docker;
using Xunit;

namespace Akka.Persistence.Linq2Db.BenchmarkTests.Docker.Linq2Db
{
[CollectionDefinition("PostgreSQLSpec")]
public sealed class PostgreSQLSpecsFixture : ICollectionFixture<PostgreSQLFixture>
{
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Akka.Configuration;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker;
using Akka.Persistence.Linq2Db.BenchmarkTests;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker.Docker;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.Linq2Db.BenchmarkTests.Docker.SqlCommon
namespace Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests.SqlCommon
{
[Collection("SqlServerSpec")]
public class DockerBatchingSqlServerJournalPerfSpec : L2dbJournalPerfSpec
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Akka.Configuration;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker;
using Akka.Persistence.Linq2Db.BenchmarkTests;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker.Docker;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.Linq2Db.BenchmarkTests.Docker.SqlCommon
namespace Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests.SqlCommon
{
[Collection("PostgreSQLSpec")]
public class DockerPostgreSQLJournalPerfSpec : L2dbJournalPerfSpec
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Akka.Configuration;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker;
using Akka.Persistence.Linq2Db.BenchmarkTests;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker.Docker;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.Linq2Db.BenchmarkTests.Docker.SqlCommon
namespace Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests.SqlCommon
{
[Collection("SqlServerSpec")]
public class DockerSqlServerJournalPerfSpec : L2dbJournalPerfSpec
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Akka.Persistence.Sql.Linq2Db.Tests.Docker;
using Akka.Persistence.Sql.Linq2Db.Tests.Docker.Docker;
using Xunit;

namespace Akka.Persistence.Linq2Db.BenchmarkTests.Docker.Linq2Db
{
[CollectionDefinition("SqlServerSpec")]
public sealed class SqlServerSpecsFixture : ICollectionFixture<SqlServerFixture>
{
}
}
7 changes: 7 additions & 0 deletions Akka.Persistence.Linq2Db.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_", "_", "{20C26B2D-59EA-42
ProjectSection(SolutionItems) = preProject
src\common.props = src\common.props
README.md = README.md
RELEASE_NOTES.md = RELEASE_NOTES.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests", "Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests\Akka.Persistence.Linq2Db.Benchmark.DockerComparisonTests.csproj", "{170698FA-DA1E-40BC-896D-AFA67976C0EB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -71,6 +74,10 @@ Global
{095E392C-C439-4EBC-ABCB-6AA87FCBD9E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{095E392C-C439-4EBC-ABCB-6AA87FCBD9E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{095E392C-C439-4EBC-ABCB-6AA87FCBD9E9}.Release|Any CPU.Build.0 = Release|Any CPU
{170698FA-DA1E-40BC-896D-AFA67976C0EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{170698FA-DA1E-40BC-896D-AFA67976C0EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{170698FA-DA1E-40BC-896D-AFA67976C0EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{170698FA-DA1E-40BC-896D-AFA67976C0EB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
63 changes: 32 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

A Cross-SQL-DB Engine Akka.Persistence plugin with broad database compatibility thanks to Linq2Db.

This is a Fairly-Naive port of the amazing akka-persistence-jdbc package from Scala to C#.
This is a port of the amazing akka-persistence-jdbc package from Scala, with a few improvements based on C# as well as our choice of data library.

Please read the documentation carefully. Some features may be specific to use case and have trade-offs (namely, compatibility modes)

## Status

- Usable for basic Read/Writes

- Implements the following for `Akka.Persistence.Query`:
- IPersistenceIdsQuery
- ICurrentPersistenceIdsQuery
Expand All @@ -20,9 +20,7 @@ Please read the documentation carefully. Some features may be specific to use ca
- ICurrentAllEventsQuery
- Snapshot Store Support

#### This is still a WORK IN PROGRESS

**Pull Requests are Welcome** but please note this is still considered 'work in progress' and only used if one understands the risks. While the TCK Specs pass you should still test in a 'safe' non-production environment carefully before deciding to fully deploy.
See something you want to add or improve? **Pull Requests are Welcome!**

Working:

Expand Down Expand Up @@ -102,27 +100,8 @@ Compatibility with existing Providers is partially implemented via `table-compat

# Performance

Tests based on i-7 8750H, 32GB Ram, 2TB SSD, Windows 10 version Version 10.0.19041.630.
Databases running on Docker WSL2.

All numbers are in msg/sec.

|Test |SqlServer (normal) | SqlServer Batching | Linq2Db |vs Normal| vs Batching|
|:------------- |:------------- | :----------: | -----------: | -----------: | -----------: |
|Persist | 164|427| 235|143.29%|55.04%|
|PersistAll | 782|875| 5609|717.26%|641.03%|
|PersistAsync | 630|846| 16099|2555.40%|1902.96%|
|PersistAllAsync | 2095|902| 15681|748.50%|1738.47%|
|PersistGroup10 | 590|680| 1069|181.19%|157.21%|
|PersistGroup100 | 607|965| 5537|912.19%|573.78%|
|PersistGroup200 | 628|1356| 7966|1268.47%|587.46%|
|PersistGroup25 | 629|675| 2189|348.01%|324.30%|
|PersistGroup400 | 612|1011| 7237|1182.52%|715.83%|
|PersistGroup50 | 612|654| 3867|631.86%|591.28%|
|Recovering | 41903|38766| 42592|101.64%|109.87%|
|Recovering8 | 75466|65515| 63960|84.75%|97.63%|
|RecoveringFour | 59259|51355| 58437|98.61%|113.79%|
|RecoveringTwo | 41745|35512| 41108|98.47%|115.76%|
Updated Performance numbers pending.

## Sql.Common Compatibility modes

- Delete Compatibility mode is available.
Expand All @@ -140,19 +119,21 @@ All numbers are in msg/sec.

### Journal:

Please note that you -must- provide a Connection String and Provider name.
Please note that you -must- provide a Connection String (`connection-string`) and Provider name (`provider-name`).

- Refer to the Members of `LinqToDb.ProviderName` for included providers.
- Note: For best performance, one should use the most specific provider name possible. i.e. `LinqToDB.ProviderName.SqlServer2012` instead of `LinqToDB.ProviderName.SqlServer`. Otherwise certain provider detections have to run more frequently which may impair performance slightly.

- `parallelism` controls the number of Akka.Streams Queues used to write to the DB.
- Default in JVM is `8`. We use `2`
- For SQL Server, Based on testing `2` is a fairly optimal number in .NET and thusly chosen as the default. You may wish to adjust up if you are dealing with a large number of actors.
- Default in JVM is `8`. We use `3`
- For SQL Server, Based on testing `3` is a fairly optimal number in .NET and thusly chosen as the default. You may wish to adjust up if you are dealing with a large number of actors.
- Testing indicates that `2` will provide performance on par or better than both batching and non-batching journal.
- For SQLite, you may want to just put `1` here, because SQLite allows at most a single writer at a time even in WAL mode.
- Keep in mind there may be some latency/throughput trade-offs if your write-set gets large.
- Note that these run on the threadpool, not on dedicated threads. Setting this number too high may steal work from other actors.
- It's worth noting that LinqToDb's Bulk Copy implementations are -very- efficient here, since under many DBs the batch can be done in a single round-trip.
- Note that unless `materializer-dispatcher` is changed, by default these run on the threadpool, not on dedicated threads. Setting this number too high may steal work from other actors.
- It's worth noting that LinqToDb's Bulk Copy implementations are very efficient here, since under many DBs the batch can be done in a single async round-trip.
- `materializer-dispatcher` may be used to change the dispatcher that the Akka.Streams Queues use for scheduling.
- You can define a different dispatcher here if worried about stealing from the thread-pool, for instance a Dedicated thread-pool dispatcher.
- `logical-delete` if `true` will only set the deleted flag for items, i.e. will not actually delete records from DB.
- if `false` all records are set as deleted, and then all but the top record is deleted. This top record is used for sequence number tracking in case no other records exist in the table.
- `delete-compatibility-mode` specifies to perform deletes in a way that is compatible with Akka.Persistence.Sql.Common.
Expand All @@ -161,6 +142,14 @@ Please note that you -must- provide a Connection String and Provider name.
- `use-clone-connection` is a bit of a hack. Currently Linq2Db has a performance penalty for custom mapping schemas. Cloning the connection is faster but may not work for all scenarios.
- tl;dr - If a password or similar is in the connection string, leave `use-clone-connection` set to `false`.
- If you don't have a password or similar, run some tests with it set to `true`. You'll see improved write and read performance.
- Batching options:
- `batch-size` controls the maximum size of the batch used in the Akka.Streams Batch. A single batch is written to the DB in a transaction, with 1 or more round trips.
- If more than `batch-size` is in a single `AtomicWrite`, That atomic write will still be atomic, just treated as it's own batch.
- `db-round-trip-max-batch-size` tries to hint to Linq2Db multirow insert the maximum number of rows to send in a round-trip to the DB.
- multiple round-trips will still be contained in a single transaction.
- You will want to Keep this number higher than `batch-size`, if you are persisting lots of events with `PersistAll/(Async)`.
- `prefer-parameters-on-multirow-insert` controls whether Linq2Db will try to use parameters instead of building raw strings for inserts.
- Linq2Db is incredibly speed and memory efficent at building binary strings. In most cases, this will be faster than the cost of parsing/marshalling parameters by ADO and the DB.
- For Table Configuration:
- Note that Tables/Columns will be created with the casing provided, and selected in the same way (i.e. if using a DB with case sensitive columns, be careful!)

Expand Down Expand Up @@ -209,6 +198,18 @@ akka.persistence {
#larger batches may be better if you have A fast/local DB.
batch-size = 100
#This batch size controls the maximum number of rows that will be sent
#In a single round trip to the DB. This is different than the -actual- batch size,
#And intentionally set larger than batch-size,
#to help atomicwrites be faster
#Note that Linq2Db may use a lower number per round-trip in some cases.
db-round-trip-max-batch-size = 1000
#Linq2Db by default will use a built string for multi-row inserts
#Somewhat counterintuitively, this is faster than using parameters in most cases,
#But if you would prefer parameters, you can set this to true.
prefer-parameters-on-multirow-insert = true
# Denotes the number of messages retrieved
# Per round-trip to DB on recovery.
# This is to limit both size of dataset from DB (possibly lowering locking requirements)
Expand Down
17 changes: 17 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
#### 1.4.21 July 6 2021 ####
**First official Release for Akka.Persistence.Linq2Db**

Akka.Persistence.Linq2Db is an Akka.Net Persistence plug-in that is designed for both high performance as well as easy cross-database compatibility.

There is a compatibility mode also available for those who wish to migrate from the existing Sql.Common journals.

This release contains fixes for Transactions around batched writes, a fix for Sequence Number reading on Aggressive PersistAsync Usage, improved serialization/deserialization pipelines for improved write speed, and easier snapshot compatibility with Akka.Persistence.Sql.Common.

We are still looking for community help with adding tests/configurations for MySql and Oracle, as well as trying out the new plugin and [providing feedback](https://github.com/akkadotnet/Akka.Persistence.Linq2Db/issues).

[Please refer to the project page](https://github.com/akkadotnet/Akka.Persistence.Linq2Db/) for information on configuration.





#### 0.90.1 Feb 3 2021 ####
**Preview Release for Akka.Persistence.Linq2Db**

Expand Down
2 changes: 2 additions & 0 deletions build-system/windows-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ trigger:
include:
- refs/tags/*

pr: none

variables:
- group: signingSecrets #create this group with SECRET variables `signingUsername` and `signingPassword`
- group: nugetKeys #create this group with SECRET variables `nugetKey`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka" Version="1.4.14" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.3.9" />
<PackageReference Include="Akka.Persistence.Redis" Version="1.4.4" />
<PackageReference Include="Akka" Version="1.4.21" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.4.19" />
<PackageReference Include="Akka.Persistence.Redis" Version="1.4.20" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="redis-inside" Version="3.3.0" />
<PackageReference Include="StackExchange.Redis" Version="2.1.58" />
<PackageReference Include="StackExchange.Redis" Version="2.2.62" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class = ""{0}""
#connection-string = ""FullUri=file:test.db&cache=shared""
provider-name = """ + LinqToDB.ProviderName.SqlServer2017 + @"""
use-clone-connection = true
#prefer-parameters-on-multirow-insert = true
tables.journal {{
auto-init = true
warn-on-auto-init-fail = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka" Version="1.4.14" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.3.9" />
<PackageReference Include="Akka.Persistence.Redis" Version="1.4.4" />
<PackageReference Include="Akka" Version="1.4.21" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.4.19" />
<PackageReference Include="Akka.Persistence.Redis" Version="1.4.20" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="redis-inside" Version="3.3.0" />
<PackageReference Include="StackExchange.Redis" Version="2.1.58" />
<PackageReference Include="StackExchange.Redis" Version="2.2.62" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ internal void MeasureGroup(Func<TimeSpan, string> msg, Action block, int numMsg,
{
var measurements = new List<TimeSpan>(MeasurementIterations);

block();
block(); //warm-up

int i = 0;
Expand Down Expand Up @@ -550,7 +551,7 @@ public void PersistenceActor_performance_must_measure_Recovering8()
FeedAndExpectLastSpecific(p6, "p", Commands);
FeedAndExpectLastSpecific(p7, "p", Commands);
FeedAndExpectLastSpecific(p8, "p", Commands);
MeasureGroup(d => $"Recovering {EventsCount} took {d.TotalMilliseconds} ms", () =>
MeasureGroup(d => $"Recovering {EventsCount} took {d.TotalMilliseconds} ms , {(EventsCount*8 / d.TotalMilliseconds) * 1000} total msg/sec", () =>
{
var task1 = Task.Run(()=>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka" Version="1.4.14" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.3.9" />
<PackageReference Include="Akka" Version="1.4.21" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.4.19" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Akka" Version="1.4.14" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.3.9" />
<PackageReference Include="Akka" Version="1.4.21" />
<PackageReference Include="Akka.Persistence.PostgreSql" Version="1.4.19" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public async Task Can_Recover_SqlCommon_Journal()
persistRef.Tell(new SomeEvent(){EventName = "rec-test", Guid = ourGuid, Number = 1});
Assert.True(persistRef.Ask<bool>(new ContainsEvent(){Guid = ourGuid}, TimeSpan.FromSeconds(5)).Result);
await persistRef.GracefulStop(TimeSpan.FromSeconds(5));
await Task.Delay(1000);
persistRef = sys1.ActorOf(Props.Create(() =>
new JournalCompatActor(NewJournal,
"p-1")), "test-recover-1");
Expand Down Expand Up @@ -90,6 +91,7 @@ public async Task SqlCommon_Journal_Can_Recover_L2Db_Journal()
persistRef.Tell(new SomeEvent(){EventName = "rec-test", Guid = ourGuid, Number = 1});
Assert.True(persistRef.Ask<bool>(new ContainsEvent(){Guid = ourGuid}, TimeSpan.FromSeconds(5)).Result);
await persistRef.GracefulStop(TimeSpan.FromSeconds(5));
await Task.Delay(1000);
persistRef = sys1.ActorOf(Props.Create(() =>
new JournalCompatActor(OldJournal,
"p-3")), "test-recover-2");
Expand Down
Loading

0 comments on commit 170c39a

Please sign in to comment.