Skip to content

Commit

Permalink
Merge with 5.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
sakno committed Jan 23, 2024
2 parents 15d9f2d + a3b9e5b commit 30fdf29
Show file tree
Hide file tree
Showing 25 changed files with 795 additions and 139 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
Release Notes
====

# 01-23-2024
<a href="https://www.nuget.org/packages/dotnext/5.0.1">DotNext 5.0.1</a>
* Smallish performance improvements of dynamic buffers

<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.0.1">DotNext.Metaprogramming 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.unsafe/5.0.1">DotNext.Unsafe 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.threading/5.0.1">DotNext.Threading 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.io/5.0.1">DotNext.IO 5.0.1</a>
* Improved performance of `FileWriter` and `FileBufferingWriter` classes by utilizing Scatter/Gather IO
* Reduced memory allocations required by async methods of `FileWriter` and `FileBufferingWriter` classes
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.0.1">DotNext.Net.Cluster 5.0.1</a>
* Improved IO performance of Persistent WAL due to related improvements in DotNext.IO library
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.0.1">DotNext.AspNetCore.Cluster 5.0.1</a>
* Updated dependencies

# 01-14-2024
.NEXT 5.0.0 has been released! The primary goal of the new release is migration to .NET 8 to fully utilize its features such as [Generic Math](https://learn.microsoft.com/en-us/dotnet/standard/generics/math) and static abstract interface members. 5.x is not fully backward compatible with 4.x because of breaking changes in the API. Most of changes done in DotNext, DotNext.IO, and DotNext.Unsafe libraries. UDP transport for Raft is completely removed in favor of existing TCP implementation. There is a plan to implement multiplexed TCP connection and Raft sharding. New features:
* Numeric ranges for LINQ. Thanks to Generic Math
Expand Down
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,31 @@ All these things are implemented in 100% managed code on top of existing .NET AP
* [NuGet Packages](https://www.nuget.org/profiles/rvsakno)

# What's new
Release Date: 01-14-2024
Release Date: 01-23-2024

.NEXT 5.0.0 has been released! The primary goal of the new release is migration to .NET 8 to fully utilize its features such as [Generic Math](https://learn.microsoft.com/en-us/dotnet/standard/generics/math) and static abstract interface members. 5.x is not fully backward compatible with 4.x because of breaking changes in the API. Most of changes done in DotNext, DotNext.IO, and DotNext.Unsafe libraries. UDP transport for Raft is completely removed in favor of existing TCP implementation. There is a plan to implement multiplexed TCP connection and Raft sharding. New features:
* Numeric ranges for LINQ. Thanks to Generic Math
* Little-endian and big-endian readers/writer for various buffer types. Again thanks to Generic Math
* UTF-8 formatting support for various buffer types
<a href="https://www.nuget.org/packages/dotnext/5.0.1">DotNext 5.0.1</a>
* Smallish performance improvements of dynamic buffers

DotNext.Reflection library is deprecated and no longer maintained.
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.0.1">DotNext.Metaprogramming 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.unsafe/5.0.1">DotNext.Unsafe 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.threading/5.0.1">DotNext.Threading 5.0.1</a>
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.io/5.0.1">DotNext.IO 5.0.1</a>
* Improved performance of `FileWriter` and `FileBufferingWriter` classes by utilizing Scatter/Gather IO
* Reduced memory allocations required by async methods of `FileWriter` and `FileBufferingWriter` classes
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.0.1">DotNext.Net.Cluster 5.0.1</a>
* Improved IO performance of Persistent WAL due to related improvements in DotNext.IO library
* Updated dependencies

<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.0.1">DotNext.AspNetCore.Cluster 5.0.1</a>
* Updated dependencies

Changelog for previous versions located [here](./CHANGELOG.md).

Expand Down
2 changes: 1 addition & 1 deletion src/DotNext.IO/DotNext.IO.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Authors>.NET Foundation and Contributors</Authors>
<Company />
<Product>.NEXT Family of Libraries</Product>
<VersionPrefix>5.0.0</VersionPrefix>
<VersionPrefix>5.0.1</VersionPrefix>
<VersionSuffix></VersionSuffix>
<AssemblyName>DotNext.IO</AssemblyName>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
189 changes: 189 additions & 0 deletions src/DotNext.IO/IO/FileBufferingWriter.Utils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using System.Collections;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks.Sources;

namespace DotNext.IO;

using Intrinsics = Runtime.Intrinsics;

public partial class FileBufferingWriter : IDynamicInterfaceCastable
{
private readonly Action writeCallback, writeAndFlushCallback, writeAndCopyCallback;
private ReadOnlyMemory<byte> secondBuffer;
private ManualResetValueTaskSourceCore<byte> source;
private ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter;

private ReadOnlyMemory<byte> GetBuffer(int index) => index switch
{
0 => WrittenMemory,
1 => secondBuffer,
_ => ReadOnlyMemory<byte>.Empty,
};

private IEnumerator<ReadOnlyMemory<byte>> EnumerateBuffers()
{
yield return WrittenMemory;
yield return secondBuffer;
}

[DynamicInterfaceCastableImplementation]
private interface IBufferList : IReadOnlyList<ReadOnlyMemory<byte>>
{
int IReadOnlyCollection<ReadOnlyMemory<byte>>.Count => 2;

ReadOnlyMemory<byte> IReadOnlyList<ReadOnlyMemory<byte>>.this[int index]
=> Unsafe.As<FileBufferingWriter>(this).GetBuffer(index);

IEnumerator<ReadOnlyMemory<byte>> IEnumerable<ReadOnlyMemory<byte>>.GetEnumerator()
=> Unsafe.As<FileBufferingWriter>(this).EnumerateBuffers();

IEnumerator IEnumerable.GetEnumerator()
=> Unsafe.As<FileBufferingWriter>(this).EnumerateBuffers();
}

private void GetAsyncResult(short token)
{
try
{
source.GetResult(token);
}
finally
{
source.Reset();
}
}

private void OnWrite()
{
var awaiter = this.awaiter;
this.awaiter = default;

var secondBuffer = this.secondBuffer;
this.secondBuffer = default;

try
{
awaiter.GetResult();

filePosition += secondBuffer.Length + position;
position = 0;
}
catch (Exception e)
{
source.SetException(e);
return;
}

source.SetResult(0);
}

private void OnWriteAndFlush()
{
Debug.Assert(fileBackend is not null);

var awaiter = this.awaiter;
this.awaiter = default;

var secondBuffer = this.secondBuffer;
this.secondBuffer = default;

try
{
awaiter.GetResult();

filePosition += secondBuffer.Length + position;
position = 0;
RandomAccess.FlushToDisk(fileBackend);
}
catch (Exception e)
{
source.SetException(e);
return;
}

source.SetResult(0);
}

private void OnWriteAndCopy()
{
var awaiter = this.awaiter;
this.awaiter = default;

var secondBuffer = this.secondBuffer;
this.secondBuffer = default;

try
{
awaiter.GetResult();

filePosition += position;
secondBuffer.CopyTo(buffer.Memory);
position = secondBuffer.Length;
}
catch (Exception e)
{
source.SetException(e);
return;
}

source.SetResult(0);
}

private ValueTask Submit(ValueTask task, Action callback)
{
awaiter = task.ConfigureAwait(false).GetAwaiter();
if (awaiter.IsCompleted)
{
callback();
}
else
{
awaiter.UnsafeOnCompleted(callback);
}

return new((IValueTaskSource)this.As<IDynamicInterfaceCastable>(), source.Version);
}

[DynamicInterfaceCastableImplementation]
private interface IProxyValueTaskSource : IValueTaskSource
{
ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
{
ref var source = ref Unsafe.As<FileBufferingWriter>(this).source;
return source.GetStatus(token);
}

void IValueTaskSource.GetResult(short token)
=> Unsafe.As<FileBufferingWriter>(this).GetAsyncResult(token);

void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
{
ref var source = ref Unsafe.As<FileBufferingWriter>(this).source;
source.OnCompleted(continuation, state, token, flags);
}
}

[ExcludeFromCodeCoverage]
bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
{
if (interfaceType.IsOneOf([Intrinsics.TypeOf<IReadOnlyList<ReadOnlyMemory<byte>>>(), Intrinsics.TypeOf<IValueTaskSource>()]))
return true;

return throwIfNotImplemented ? throw new InvalidCastException() : false;
}

[ExcludeFromCodeCoverage]
RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType)
{
if (interfaceType.IsOneOf([Intrinsics.TypeOf<IReadOnlyList<ReadOnlyMemory<byte>>>(), Intrinsics.TypeOf<IReadOnlyCollection<ReadOnlyMemory<byte>>>()]))
return Intrinsics.TypeOf<IBufferList>();

if (interfaceType.Equals(Intrinsics.TypeOf<IValueTaskSource>()))
return Intrinsics.TypeOf<IProxyValueTaskSource>();

throw new InvalidCastException();
}
}
Loading

0 comments on commit 30fdf29

Please sign in to comment.