From 529cae35e93975ba16955541aab4fd029d9d1e6f Mon Sep 17 00:00:00 2001 From: Badrish Chandramouli Date: Mon, 15 Nov 2021 11:25:27 -0800 Subject: [PATCH 1/2] Make PendingFlushList never error out in stressful situations. Current implementation uses lock for ~5-10% perf degradation over prior structure. --- cs/src/core/Allocator/AllocatorBase.cs | 20 +++------- cs/src/core/Allocator/PendingFlushList.cs | 47 +++++++++-------------- 2 files changed, 24 insertions(+), 43 deletions(-) diff --git a/cs/src/core/Allocator/AllocatorBase.cs b/cs/src/core/Allocator/AllocatorBase.cs index 3a089d3f8..49ff3e28e 100644 --- a/cs/src/core/Allocator/AllocatorBase.cs +++ b/cs/src/core/Allocator/AllocatorBase.cs @@ -1752,22 +1752,12 @@ public void AsyncFlushPages(long fromAddress, long untilAddress) } // Enqueue work in shared queue - if (PendingFlush[index].Add(asyncResult)) - { - // Perform work from shared queue if possible - if (PendingFlush[index].RemoveNextAdjacent(FlushedUntilAddress, out PageAsyncFlushResult request)) - { - WriteAsync(request.fromAddress >> LogPageSizeBits, AsyncFlushPageCallback, request); - } - } - else + PendingFlush[index].Add(asyncResult); + + // Perform work from shared queue if possible + if (PendingFlush[index].RemoveNextAdjacent(FlushedUntilAddress, out PageAsyncFlushResult request)) { - // Because we are invoking the callback away from the usual codepath, need to externally - // ensure that flush address are updated in order - while (FlushedUntilAddress < asyncResult.fromAddress) Thread.Yield(); - // Could not add to pending flush list, treat as a failed write - // Use a special errorCode to convey that this is not from a syscall - AsyncFlushPageCallback(16000, 0, asyncResult); + WriteAsync(request.fromAddress >> LogPageSizeBits, AsyncFlushPageCallback, request); } } else diff --git a/cs/src/core/Allocator/PendingFlushList.cs b/cs/src/core/Allocator/PendingFlushList.cs index 565ee9fc0..c38d964cc 100644 --- a/cs/src/core/Allocator/PendingFlushList.cs +++ b/cs/src/core/Allocator/PendingFlushList.cs @@ -1,38 +1,25 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System.Threading; +using System.Collections.Generic; namespace FASTER.core { class PendingFlushList { - const int maxSize = 8; - const int maxRetries = 10; - public PageAsyncFlushResult[] list; + public readonly LinkedList> list; public PendingFlushList() { - list = new PageAsyncFlushResult[maxSize]; + list = new(); } - public bool Add(PageAsyncFlushResult t) + public void Add(PageAsyncFlushResult t) { - int retries = 0; - do + lock (list) { - for (int i = 0; i < maxSize; i++) - { - if (list[i] == default) - { - if (Interlocked.CompareExchange(ref list[i], t, default) == default) - { - return true; - } - } - } - } while (retries++ < maxRetries); - return false; + list.AddFirst(t); + } } /// @@ -40,15 +27,17 @@ public bool Add(PageAsyncFlushResult t) /// public bool RemoveNextAdjacent(long address, out PageAsyncFlushResult request) { - for (int i=0; i req /// public bool RemovePreviousAdjacent(long address, out PageAsyncFlushResult request) { - for (int i = 0; i < maxSize; i++) + lock (list) { - request = list[i]; - if (request?.untilAddress == address) + for (var it = list.First; it != null;) { - if (Interlocked.CompareExchange(ref list[i], null, request) == request) + request = it.Value; + if (request.untilAddress == address) { + list.Remove(it); return true; } + it = it.Next; } } request = null; From b7fb2f770eb451c875d7b5d3480d0db6106bfd7f Mon Sep 17 00:00:00 2001 From: Badrish Chandramouli Date: Mon, 15 Nov 2021 11:25:43 -0800 Subject: [PATCH 2/2] nit --- cs/src/core/Allocator/PendingFlushList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cs/src/core/Allocator/PendingFlushList.cs b/cs/src/core/Allocator/PendingFlushList.cs index c38d964cc..a3776dddd 100644 --- a/cs/src/core/Allocator/PendingFlushList.cs +++ b/cs/src/core/Allocator/PendingFlushList.cs @@ -5,7 +5,7 @@ namespace FASTER.core { - class PendingFlushList + sealed class PendingFlushList { public readonly LinkedList> list;