8000 More efficient cache use by pshirshov · Pull Request #7 · 7mind/sick · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

More efficient cache use #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 16 additions & 23 deletions json-sick-csharp/SickSharp.Test/CacheTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Security.Cryptography;
using SickSharp.Format;
using SickSharp.IO;
using SickSharp.Primitives;

namespace SickSharp.Test;
Expand All @@ -26,30 +26,26 @@ public static void WriteRandomFile(string filePath, long sizeInBytes)
}
}
}

public static byte[] ReadBytesFromFileStream(Stream fileStream, long offset, int size)
{
if (fileStream == null)
throw new ArgumentNullException(nameof(fileStream));
if (offset < 0 || offset >= fileStream.Length)
throw new ArgumentOutOfRangeException(nameof(offset), "Offset is out of file bounds.");
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size), "Size must be non-negative.");
if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));
if (offset < 0 || offset >= fileStream.Length) throw new ArgumentOutOfRangeException(nameof(offset), "Offset is out of file bounds.");
if (size < 0) throw new ArgumentOutOfRangeException(nameof(size), "Size must be non-negative.");

int bytesToRead = size; //(int)Math.Min(size, fileStream.Length - offset);
byte[] buffer = new byte[bytesToRead];

fileStream.Seek(offset, SeekOrigin.Begin);
int bytesRead = fileStream.ReadUpTo(buffer, 0, bytesToRead);
Debug.Assert(bytesRead == size);
return buffer;
}


[SetUp]
public void Setup()
{

}


Expand All @@ -59,8 +55,8 @@ public void Test_NonallocCache()
var tempFilePath = Path.GetTempFileName();
WriteRandomFile(tempFilePath, _fileSize);

var f1 = File.Open(tempFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var f2 = new NonAllocPageCachedStream(new PageCachedFile(tempFilePath, 4192, ISickProfiler.Noop()));
var f1 = File.Open(tempFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var f2 = new PageCachedStream(new PageCachedFile(tempFilePath, 4192, ISickProfiler.Noop()));

CheckCorrectness(f1, f2);

Expand All @@ -75,7 +71,7 @@ private static void CheckCopy(Stream f2)
f2.CopyTo(ms);
}
}

public void CheckCorrectness(Stream f1, Stream f2)
{
var rng = new Random();
Expand All @@ -86,7 +82,7 @@ public void CheckCorrectness(Stream f1, Stream f2)
CompareSpans(f1, f2, 1, 4191);
CompareSpans(f1, f2, 1, 4192);
CompareSpans(f1, f2, 1, 4193);

CompareSpans(f1, f2, 4191, 8000);
CompareSpans(f1, f2, 4192, 8000);
CompareSpans(f1, f2, 4193, 8000);
Expand All @@ -102,25 +98,22 @@ public void CheckCorrectness(Stream f1, Stream f2)
CompareSpans(f1, f2, _fileSize - 299, 299);
CompareSpans(f1, f2, _fileSize - 300, 300);
CompareSpans(f1, f2, _fileSize - 301, 301);

CompareSpans(f1, f2, _fileSize - 4192, 4192);
CompareSpans(f1, f2, _fileSize - 4193, 4192);

CompareSpans(f1, f2, _fileSize - 16383, 16383);
CompareSpans(f1, f2, _fileSize - 16384, 16384);
CompareSpans(f1, f2, _fileSize - 16385, 16385);





for (int i = 0; i < 10000; i++)
{
var offset = rng.NextInt64(0, _fileSize - 1);
var count = rng.Next(1, (int)(_fileSize - offset - 1));

CompareSpans(f1, f2, offset, count);
}


}

private static void CompareSpans(Stream f1, Stream f2, long offset, int count)
Expand Down
16 changes: 4 additions & 12 deletions json-sick-csharp/SickSharp.Test/ExtendedCacheTest.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
using System.Diagnostics;
using SickSharp.Format;
using SickSharp.IO;

namespace SickSharp.Test;

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using NUnit.Framework;


// autogenerated, more or less reasonable
[TestFixture]
public class PageCachedFileTests
Expand Down Expand Up @@ -65,7 +56,7 @@ public void ConcurrentGetPage_SamePage_LoadsOnce()
{
using var cache = new PageCachedFile(_tempFile, BasePageSize, ISickProfiler.Noop());
byte[][] results = new byte[2][];

#pragma warning disable CS8601 // Possible null reference assignment.
Parallel.Invoke(
() => results[0] = cache.GetPage(0),
Expand Down Expand Up @@ -101,6 +92,7 @@ void LoadPage(int page)
#endregion

#region Disposal Tests

[Test]
public void AfterDispose_ThrowsOnAccess()
{
Expand Down Expand Up @@ -155,7 +147,7 @@ public void HighConcurrency_StressTest()
var page = random.Next(0, cache.TotalPages);
var data = cache.GetPage(page);
Assert.NotNull(data);
Assert.IsTrue(data.Length == BasePageSize || data.Length == 42);
Assert.IsTrue(data.Length == BasePageSize || data.Length == 42);
}
});

Expand Down
102 changes: 47 additions & 55 deletions json-sick-csharp/SickSharp.Test/SickTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using SickSharp.Format;
using SickSharp.Format.Tables;
using SickSharp.IO;
using Index = SickSharp.Encoder.Index;

namespace SickSharp.Test;
Expand All @@ -23,11 +24,7 @@ public void Setup()
{
Directory.CreateDirectory(PathOut);
_files = Directory.EnumerateFiles(PathInput, "*.json", SearchOption.AllDirectories).ToList();
}

[Test]
public void Test1_EncodeAll()
{
foreach (var file in _files)
{
var fi = new FileInfo(file);
Expand All @@ -41,45 +38,44 @@ public void Test1_Queries()
{
var input = Path.Join(PathOut, "petstore-with-external-docs-CS.bin");

using (var reader = SickReader.OpenFile(input, ISickCacheManager.GlobalPerFile(), ISickProfiler.Noop(),
inMemoryThreshold: 32768))
using (var reader = SickReader.OpenFile(input, ISickCacheManager.NoCache, ISickProfiler.Noop(),
loadInMemoryThreshold: 32768))
{
var rootRef = reader.GetRoot(RootName)!;
var root = reader.ReadRoot(RootName);

var o1 = (JStr)reader.Query(rootRef, "info.version");
Assert.That(o1.Value, Is.EqualTo("1.0.0"));
var o1 = root.Query("info.version").AsString();
Assert.That(o1, Is.EqualTo("1.0.0"));

var o2 = (JStr)reader.Query(rootRef, "swagger");
Assert.That(o2.Value, Is.EqualTo("2.0"));
var o2 = root.Query("swagger").AsString();
Assert.That(o2, Is.EqualTo("2.0"));

var o3 = (JStr)reader.Query(rootRef, "schemes[0]");
Assert.That(o3.Value, Is.EqualTo("http"));
var o3 = root.Query("schemes[0]").AsString();
Assert.That(o3, Is.EqualTo("http"));

var o4 = (JStr)reader.Query(rootRef, "schemes.[0]");
Assert.That(o4.Value, Is.EqualTo("http"));
var o4 = root.Query("schemes.[0]").AsString();
Assert.That(o4, Is.EqualTo("http"));

var o5 = (JStr)reader.Query(rootRef, "schemes.[-1]");
Assert.That(o5.Value, Is.EqualTo("http"));
var o5 = root.Query("schemes.[-1]").AsString();
Assert.That(o5, Is.EqualTo("http"));
}
}

[Test]
public void Query_Benchmark()
public void Test_Query_Benchmark()
{
var input = Path.Join(PathOut, "petstore-with-external-docs-CS.bin");

using (var reader = SickReader.OpenFile(input, ISickCacheManager.GlobalPerFile(), ISickProfiler.Noop(),
inMemoryThreshold: 0))
using (var reader = SickReader.OpenFile(input, ISickCacheManager.NoCache, ISickProfiler.Noop(), loadInMemoryThreshold: 0))
{
for (int i = 0; i < 500000; i++)
{
var rootRef = reader.GetRoot(RootName)!;
var o3 = (JStr)reader.Query(rootRef, "schemes[0]");
var root = reader.ReadRoot(RootName);
var o3 = root.Query("schemes[0]").AsString();
Debug.Assert(o3 != null);
}
}
}

//
// [Test]
// public void Test3_repro()
Expand All @@ -98,7 +94,7 @@ public void Query_Benchmark()
// }


public int Traverse(Ref reference, SickReader reader, int count, short limit)
public int Traverse(SickJson json, int count, short limit)
{
// Console.WriteLine(reader.ToJson(reference));

Expand All @@ -109,56 +105,54 @@ public int Traverse(Ref reference, SickReader reader, int count, short limit)
return count;
}

if (reference.Kind == RefKind.Arr)
if (json is SickJson.Array arr)
{
var arr = ((JArr)reader.Resolve(reference)).Value;
if (arr.Count == 0)
{
return next;
}

Ref entry;
SickRef entrySickRef;
int index;
if (readFirst)
{
entry = arr.Content().First();
index = 0;
entrySickRef = arr.GetValues().First().Ref;
}
else
{
index = arr.Count / 2;
entry = arr.Content().ElementAt(index);
entrySickRef = arr.GetValues().ElementAt(index).Ref;
}

var entryRef = reader.ReadArrayElementRef(reference, index);
Debug.Assert(entry == entryRef);
return Traverse(entryRef, reader, next, limit);
var entry = arr.ReadIndex(index);
Debug.Assert(entry.Ref == entrySickRef);
return Traverse(entry, next, limit);
}

if (reference.Kind == RefKind.Obj)
if (json is SickJson.Object obj)
{
var obj = ((JObj)reader.Resolve(reference)).Value;
if (obj.Count == 0)
{
return next;
}

KeyValuePair<string, Ref> entry;
KeyValuePair<string, SickRef> fieldRef;
int index;
if (readFirst)
{
entry = obj.Content().First();
index = 0;
fieldRef = obj.GetReferences().First();
}
else
{
index = obj.Count / 2;
entry = obj.Content().ElementAt(index);
fieldRef = obj.GetReferences().ElementAt(index);
}

var fieldVal = reader.ReadObjectFieldRef(reference, entry.Key);
Debug.Assert(fieldVal == entry.Value);
return Traverse(entry.Value, reader, next, limit);
var field = obj.Read(fieldRef.Key);
Debug.Assert(field.Ref == fieldRef.Value);
return Traverse(field, next, limit);
}

return count;
Expand Down Expand Up @@ -187,7 +181,7 @@ public int Traverse(Ref reference, SickReader reader, int count, short limit)
//
// if (reference.Kind == RefKind.Obj)
// {
// var obj = ((JObj)reader.Resolve(reference)).Value;
// var obj = ((SickJson.Object)reader.Resolve(reference)).Value;
// if (obj.Count == 0)
// {
// return next;
Expand Down Expand Up @@ -220,32 +214,31 @@ public void Test2_Read()
var name = fi.Name;
Console.WriteLine($"Processing {name} ({fi.Length} bytes)...");

using (var reader = SickReader.OpenFile(input, ISickCacheManager.GlobalPerFile(), ISickProfiler.Noop(),
inMemoryThreshold: 32768))
using (var reader = SickReader.OpenFile(input, ISickCacheManager.NoCache, ISickProfiler.Noop(),
loadInMemoryThreshold: 32768))
{
var rootRef = reader.GetRoot(RootName);
var root = reader.ReadRoot(RootName);

Stopwatch stopwatch = new Stopwatch();
var stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine($"Going to perform {iters} traverses...");
for (int x = 0; x < iters; x++)
{
Traverse(rootRef!, reader, 0, 10);
Traverse(root, 0, 10);
}

stopwatch.Stop();
TimeSpan stopwatchElapsed = stopwatch.Elapsed;
Console.WriteLine($"Finished in {stopwatchElapsed.TotalSeconds} sec");
Console.WriteLine($"Iters/sec {Convert.ToDouble(iters) / stopwatchElapsed.TotalSeconds}");

Debug.Assert(rootRef != null, $"No root entry in {name}");
Console.WriteLine($"{name}: found {RootName}, ref={rootRef}");
Debug.Assert(root != null, $"No root entry in {name}");
Console.WriteLine($"{name}: found {RootName}, ref={root}");

switch (rootRef.Kind)
switch (root)
{
case RefKind.Obj:
Console.WriteLine(
$"{name}: object with {((JObj)reader.Resolve(rootRef)).Value.Count} elements");
case SickJson.Object obj:
Console.WriteLine($"{name}: object with {obj.Count} elements");
break;
default:
break;
Expand Down Expand Up @@ -277,8 +270,7 @@ public void DoWrite(string inPath, string outPath)
var index = Index.Create();
var root = index.append(RootName, loaded);

using (BinaryWriter binWriter =
new BinaryWriter(File.Open(outPath, FileMode.Create)))
using (BinaryWriter binWriter = new BinaryWriter(File.Open(outPath, FileMode.Create)))
{
var data = index.Serialize().data;
Console.WriteLine(
Expand Down
Loading
0