diff --git a/CHANGELOG.md b/CHANGELOG.md
index 499694672..0c57371d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,31 @@
Release Notes
====
+# 01-23-2024
+DotNext 5.0.1
+* Smallish performance improvements of dynamic buffers
+
+DotNext.Metaprogramming 5.0.1
+* Updated dependencies
+
+DotNext.Unsafe 5.0.1
+* Updated dependencies
+
+DotNext.Threading 5.0.1
+* Updated dependencies
+
+DotNext.IO 5.0.1
+* 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
+
+DotNext.Net.Cluster 5.0.1
+* Improved IO performance of Persistent WAL due to related improvements in DotNext.IO library
+* Updated dependencies
+
+DotNext.AspNetCore.Cluster 5.0.1
+* 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
diff --git a/README.md b/README.md
index 773ae80a2..b596fdf44 100644
--- a/README.md
+++ b/README.md
@@ -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
+DotNext 5.0.1
+* Smallish performance improvements of dynamic buffers
-DotNext.Reflection library is deprecated and no longer maintained.
+DotNext.Metaprogramming 5.0.1
+* Updated dependencies
+
+DotNext.Unsafe 5.0.1
+* Updated dependencies
+
+DotNext.Threading 5.0.1
+* Updated dependencies
+
+DotNext.IO 5.0.1
+* 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
+
+DotNext.Net.Cluster 5.0.1
+* Improved IO performance of Persistent WAL due to related improvements in DotNext.IO library
+* Updated dependencies
+
+DotNext.AspNetCore.Cluster 5.0.1
+* Updated dependencies
Changelog for previous versions located [here](./CHANGELOG.md).
diff --git a/src/DotNext.IO/DotNext.IO.csproj b/src/DotNext.IO/DotNext.IO.csproj
index 46a896d87..719897c8e 100644
--- a/src/DotNext.IO/DotNext.IO.csproj
+++ b/src/DotNext.IO/DotNext.IO.csproj
@@ -11,7 +11,7 @@
.NET Foundation and Contributors
.NEXT Family of Libraries
- 5.0.0
+ 5.0.1
DotNext.IO
MIT
diff --git a/src/DotNext.IO/IO/FileBufferingWriter.Utils.cs b/src/DotNext.IO/IO/FileBufferingWriter.Utils.cs
new file mode 100644
index 000000000..ba24de421
--- /dev/null
+++ b/src/DotNext.IO/IO/FileBufferingWriter.Utils.cs
@@ -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 secondBuffer;
+ private ManualResetValueTaskSourceCore source;
+ private ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter;
+
+ private ReadOnlyMemory GetBuffer(int index) => index switch
+ {
+ 0 => WrittenMemory,
+ 1 => secondBuffer,
+ _ => ReadOnlyMemory.Empty,
+ };
+
+ private IEnumerator> EnumerateBuffers()
+ {
+ yield return WrittenMemory;
+ yield return secondBuffer;
+ }
+
+ [DynamicInterfaceCastableImplementation]
+ private interface IBufferList : IReadOnlyList>
+ {
+ int IReadOnlyCollection>.Count => 2;
+
+ ReadOnlyMemory IReadOnlyList>.this[int index]
+ => Unsafe.As(this).GetBuffer(index);
+
+ IEnumerator> IEnumerable>.GetEnumerator()
+ => Unsafe.As(this).EnumerateBuffers();
+
+ IEnumerator IEnumerable.GetEnumerator()
+ => Unsafe.As(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(), source.Version);
+ }
+
+ [DynamicInterfaceCastableImplementation]
+ private interface IProxyValueTaskSource : IValueTaskSource
+ {
+ ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
+ {
+ ref var source = ref Unsafe.As(this).source;
+ return source.GetStatus(token);
+ }
+
+ void IValueTaskSource.GetResult(short token)
+ => Unsafe.As(this).GetAsyncResult(token);
+
+ void IValueTaskSource.OnCompleted(Action