Skip to content

Commit

Permalink
Increase refCache size for Memory based API (#833)
Browse files Browse the repository at this point in the history
* add single writer test

* Add user provided repro in playground.

* add user provided test
fix refCache size

* update testcase
  • Loading branch information
badrishc authored May 7, 2023
1 parent cb04d94 commit 8da1898
Show file tree
Hide file tree
Showing 6 changed files with 417 additions and 8 deletions.
11 changes: 11 additions & 0 deletions cs/FASTER.sln
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{CEDB9572-7
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResizableCacheStore", "samples\ResizableCacheStore\ResizableCacheStore.csproj", "{B4A55211-5457-44B9-8BCB-A5488C994965}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MemoryDb", "playground\MemoryDb\MemoryDb.csproj", "{6315094C-66B1-410E-9ACE-9078AF7A77CA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -335,6 +337,14 @@ Global
{B4A55211-5457-44B9-8BCB-A5488C994965}.Release|Any CPU.Build.0 = Release|x64
{B4A55211-5457-44B9-8BCB-A5488C994965}.Release|x64.ActiveCfg = Release|x64
{B4A55211-5457-44B9-8BCB-A5488C994965}.Release|x64.Build.0 = Release|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Debug|Any CPU.ActiveCfg = Debug|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Debug|Any CPU.Build.0 = Debug|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Debug|x64.ActiveCfg = Debug|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Debug|x64.Build.0 = Debug|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Release|Any CPU.ActiveCfg = Release|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Release|Any CPU.Build.0 = Release|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Release|x64.ActiveCfg = Release|x64
{6315094C-66B1-410E-9ACE-9078AF7A77CA}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -369,6 +379,7 @@ Global
{DC3E0640-9A36-43D0-AA37-A1B61B0BFBC9} = {62BC1134-B6E1-476A-B894-7CA278A8B6DE}
{AF996720-DB6C-4ED7-9693-B9531F0B119A} = {5E4C9997-3350-4761-9FC9-F27649848B1D}
{B4A55211-5457-44B9-8BCB-A5488C994965} = {62BC1134-B6E1-476A-B894-7CA278A8B6DE}
{6315094C-66B1-410E-9ACE-9078AF7A77CA} = {E6026D6A-01C5-4582-B2C1-64751490DABE}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A0750637-2CCB-4139-B25E-F2CE740DCFAC}
Expand Down
19 changes: 19 additions & 0 deletions cs/playground/MemoryDb/MemoryDb.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<Platforms>x64</Platforms>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ImplicitUsings>enable</ImplicitUsings>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\core\FASTER.core.csproj" />
</ItemGroup>

</Project>
233 changes: 233 additions & 0 deletions cs/playground/MemoryDb/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
using FASTER.core;
using System.Buffers.Binary;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System;

namespace ConsoleApp72;

using MySession = ClientSession<Memory<byte>, Memory<byte>, Memory<byte>, (IMemoryOwner<byte>, int), Empty, UserDataFunctions<Memory<byte>>>;

internal class Program
{
static async Task Main()
{
var sourceDbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "source");

WriteSimpleSourceDb(sourceDbPath);

for (var i = 0; i < 100; i++)
{
var dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"faster-{i}");
try
{
await Write(sourceDbPath, dbPath);
}
finally
{
try
{
if (Directory.Exists(dbPath))
Directory.Delete(dbPath, true);
}
catch
{
// ignore
}
}
}
}

private static readonly Random random = new();

private static void WriteSimpleSourceDb(string sourceDbPath)
{
Console.WriteLine($"Source: {sourceDbPath}");

if (Directory.Exists(sourceDbPath))
Directory.Delete(sourceDbPath, true);

using var fasterLogSettings = new FasterLogSettings(sourceDbPath);
using var fasterLog = new FasterLog(fasterLogSettings);

for (var index = 0; index < 500_000; index++)
{
using var valueBuffer = MemoryPool<byte>.Shared.Rent(1024);

random.NextBytes(valueBuffer.Memory.Span.Slice(0, 1024));

fasterLog.Enqueue(valueBuffer.Memory.Span.Slice(0, 1024));
}

fasterLog.Commit(true);
}

private const int SecondaryIndexCnt = 5;

private static async Task Write(string sourceDbPath, string dbPath)
{
Console.WriteLine(dbPath);

if (Directory.Exists(dbPath))
Directory.Delete(dbPath, true);

var mainDbPath = Path.Combine(dbPath, "main");

var tempIndexDbDirectory = Path.Combine(dbPath, "TempIndex");

using var mainLogDevice = Devices.CreateLogDevice(mainDbPath);
using var mainKvSettings = new FasterKVSettings<Memory<byte>, Memory<byte>> { LogDevice = mainLogDevice, PageSize = 1 * 1024 * 1024, SegmentSize = 32 * 1024 * 1024, CheckpointDir = mainDbPath };
using var mainKv = new FasterKV<Memory<byte>, Memory<byte>>(mainKvSettings);

var indexDevices = new List<IDevice>();
var indexSettings = new List<FasterKVSettings<Memory<byte>, Memory<byte>>>();
var indexKvs = new List<FasterKV<Memory<byte>, Memory<byte>>>();

for (var i = 0; i < SecondaryIndexCnt; i++)
{
var indexPath = Path.Combine(tempIndexDbDirectory, $"i_{i}");

var indexLogDevice = Devices.CreateLogDevice(indexPath);
var indexKvSettings = new FasterKVSettings<Memory<byte>, Memory<byte>> { LogDevice = indexLogDevice, PageSize = 1 * 1024 * 1024, SegmentSize = 32 * 1024 * 1024, CheckpointDir = indexPath };
var indexKv = new FasterKV<Memory<byte>, Memory<byte>>(indexKvSettings);

indexDevices.Add(indexLogDevice);
indexSettings.Add(indexKvSettings);
indexKvs.Add(indexKv);
}

{
using var mainKvSession = mainKv.For(UserDataFunctions<Memory<byte>>.Instance).NewSession<UserDataFunctions<Memory<byte>>>();

var indexSessions = new List<MySession>();

foreach (var indexKv in indexKvs)
{
indexSessions.Add(indexKv.For(UserDataFunctions<Memory<byte>>.Instance).NewSession<UserDataFunctions<Memory<byte>>>());
}

using var sourceLogSettings = new FasterLogSettings(sourceDbPath) { ReadOnlyMode = true };
using var sourceLog = new FasterLog(sourceLogSettings);

var recordCounter = 0;

using var sourceIterator = sourceLog.Scan(sourceLog.BeginAddress, long.MaxValue);

while (sourceIterator.GetNext(MemoryPool<byte>.Shared, out var memoryOwner, out var wholeLength, out var address))
{
recordCounter++;

using var mo = memoryOwner;

var wholeValue = memoryOwner.Memory.Slice(0, wholeLength);

var primaryKey = address;

using var primaryKeyBuffer = MemoryPool<byte>.Shared.Rent(8);

BinaryPrimitives.TryWriteInt64BigEndian(primaryKeyBuffer.Memory.Span.Slice(0, 8), primaryKey);

var primaryKeyContent = primaryKeyBuffer.Memory.Slice(0, 8);

var secondaryKeys = new List<byte[]>();

for (var i = 0; i < SecondaryIndexCnt; i++)
{
secondaryKeys.Add(memoryOwner.Memory.Slice(i * 4, 4).ToArray());
}

if (TryRead(mainKvSession, primaryKeyContent, out var mainValue))
{
using (mainValue.MemoryOwner)
{
}
}

Write(mainKvSession, primaryKeyContent, wholeValue);

for (var i = 0; i < SecondaryIndexCnt; i++)
{
var secondaryKeyContent = secondaryKeys[i].AsMemory();

if (TryRead(indexSessions[i], secondaryKeyContent, out var readItem))
{
using (readItem.MemoryOwner)
{
}
}

Write(indexSessions[i], secondaryKeyContent, primaryKeyContent);
}

if (recordCounter % 100_000 == 0)
{
Console.WriteLine($"{recordCounter}...");
}
}

Console.WriteLine($"{recordCounter} done");

foreach (var indexSession in indexSessions) indexSession.Dispose();

foreach (var indexKv in indexKvs)
{
await indexKv.TakeHybridLogCheckpointAsync(CheckpointType.FoldOver, true);
}
}

await mainKv.TakeHybridLogCheckpointAsync(CheckpointType.FoldOver, true);

foreach (var indexKv in indexKvs) indexKv.Dispose();
foreach (var indexSetting in indexSettings) indexSetting.Dispose();
foreach (var indexDevice in indexDevices) indexDevice.Dispose();
}

private static bool TryRead<TKey>(ClientSession<TKey, Memory<byte>, Memory<byte>, (IMemoryOwner<byte>, int), Empty, UserDataFunctions<TKey>> session, TKey key, out (IMemoryOwner<byte> MemoryOwner, int Length) value)
{
var (status, output) = session.Read(key);

if (status.Found)
{
value = output;
return true;
}

if (status.IsPending && session.CompletePendingWithOutputs(out var outputs, true))
{
using (outputs)
{
if (outputs.Next())
{
value = outputs.Current.Output;
return true;
}
}
}

value = default;
return false;
}

private static void Write<TKey>(ClientSession<TKey, Memory<byte>, Memory<byte>, (IMemoryOwner<byte>, int), Empty, UserDataFunctions<TKey>> session, TKey key, Memory<byte> value)
{
var status = session.Upsert(key, value);

if (status.IsPending)
{
session.CompletePending(true);
}
}
}

internal sealed class UserDataFunctions<TKey> : MemoryFunctions<TKey, byte, Empty>
{

private UserDataFunctions()
{
}

public static readonly UserDataFunctions<TKey> Instance = new();

}
6 changes: 3 additions & 3 deletions cs/src/core/VarLen/MemoryVarLenStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public unsafe ref Memory<T> AsRef(void* source)
{
if (refCache == null)
{
refCache = new (UnmanagedMemoryManager<T>, Memory<T>)[4];
for (int i = 0; i < 4; i++) refCache[i] = (new UnmanagedMemoryManager<T>(), default);
refCache = new (UnmanagedMemoryManager<T>, Memory<T>)[8];
for (int i = 0; i < 8; i++) refCache[i] = (new UnmanagedMemoryManager<T>(), default);
}
count = (count + 1) % 4;
count = (count + 1) % 8;
ref var cache = ref refCache[count];
var len = *(int*)source;
cache.Item1.SetDestination((T*)((byte*)source + sizeof(int)), len / sizeof(T));
Expand Down
6 changes: 3 additions & 3 deletions cs/src/core/VarLen/ReadOnlyMemoryVarLenStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public unsafe ref ReadOnlyMemory<T> AsRef(void* source)
{
if (manager == null)
{
manager = new (UnmanagedMemoryManager<T>, ReadOnlyMemory<T>)[4];
for (int i = 0; i < 4; i++) manager[i] = (new UnmanagedMemoryManager<T>(), default);
manager = new (UnmanagedMemoryManager<T>, ReadOnlyMemory<T>)[8];
for (int i = 0; i < 8; i++) manager[i] = (new UnmanagedMemoryManager<T>(), default);
}
count = (count + 1) % 4;
count = (count + 1) % 8;
ref var cache = ref manager[count];
cache.Item1.SetDestination((T*)((byte*)source + sizeof(int)), (*(int*)source) / sizeof(T));
cache.Item2 = cache.Item1.Memory;
Expand Down
Loading

0 comments on commit 8da1898

Please sign in to comment.