Skip to content

Commit

Permalink
more better
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Nov 20, 2023
1 parent 21dee8f commit 0a69708
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 70 deletions.
4 changes: 2 additions & 2 deletions sandbox/Benchmark/RecordPerSecondColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class LogWritesPerSecond : IColumn
{
public string Id => nameof(LogWritesPerSecond);

public string ColumnName => "recs/ms";
public string ColumnName => "recs/sec";

public bool AlwaysShow => true;

Expand All @@ -42,7 +42,7 @@ public string GetValue(Summary summary, BenchmarkCase benchmarkCase)
var statistics = summary[benchmarkCase].ResultStatistics;
var mean = TimeInterval.FromNanoseconds(statistics.Mean);
var ms = TimeInterval.FromMilliseconds(1);
return (ms.ToMilliseconds() / (mean.ToMilliseconds() / n)).ToString("F3");
return (ms.ToMilliseconds() / (mean.ToMilliseconds() / n) * 1000).ToString("F3");
}
return "-";
}
Expand Down
93 changes: 77 additions & 16 deletions sandbox/ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,52 @@
using ZLogger.Providers;
using System.Numerics;
using System.Text.Json;
using System.IO.Hashing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

var factory = LoggerFactory.Create(logging =>
{
logging.AddZLogger(zLogger =>
{
zLogger.AddConsole(console =>
zLogger.AddFile("foo.log", option =>
{
console.InternalErrorLogger = ex => Console.WriteLine(ex);
option.InternalErrorLogger = ex => Console.WriteLine(ex);

console.ConfigureEnableAnsiEscapeCode = true;
console.OutputEncodingToUtf8 = true;
console.UseJsonFormatter(formatter =>
option.UsePlainTextFormatter(formatter =>
{
formatter.IncludeProperties = IncludeProperties.None;

formatter.SetPrefixFormatter($"{0:timeonly} | {1:short} | ", (template, info) => template.Format(info.Timestamp, info.LogLevel));
});

//console.UsePlainTextFormatter(formatter =>
//{
// formatter.SetPrefixFormatter($"{0:timeonly} | {1:short} | ", (template, info) => template.Format(info.Timestamp, info.LogLevel));
//});
});
});
});

var logger = factory.CreateLogger<Program>();


var v3 = new MyVector3 { X = 10.2f, Y = 999.99f, Z = 32.1f };

logger.ZLogInformation($"foo = {v3}");
var x = 10;
var y = 20;
var z = 30;
logger.ZLogInformation($"x={x} y={y} z={z}");
//while (true)
//{
// for (int i = 0; i < 100000; i++)
// {
// logger.ZLogInformation($"x={x} y={y} z={z}");
// }

// Thread.Sleep(TimeSpan.FromSeconds(4));
//}

var hoge = "hugahuga";
Console.WriteLine(GC.GetGeneration(hoge)); // int.MaxValue

factory.Dispose();



var test = new LiteralList(new List<string?> { "hoge", null, "huga" });
test.GetHashCode();
test.Equals(test);



Expand Down Expand Up @@ -106,4 +114,57 @@ public ValueTask DisposeAsync()
{
return default;
}
}

readonly struct LiteralList : IEquatable<LiteralList>
{
readonly List<string?> literals;

public LiteralList(List<string?> literals)
{
this.literals = literals;
}

[ThreadStatic]
static XxHash3? xxhash;

public override int GetHashCode()
{
var h = xxhash;
if (h == null)
{
h = xxhash = new XxHash3();
}
else
{
h.Reset();
}

var span = CollectionsMarshal.AsSpan(literals);
foreach (var item in span)
{
h.Append(MemoryMarshal.AsBytes(item.AsSpan()));
}

// https://github.com/Cyan4973/xxHash/issues/453
// XXH3 64bit -> 32bit, okay to simple cast answered by XXH3 author.
return unchecked((int)h.GetCurrentHashAsUInt64());
}

public bool Equals(LiteralList other)
{
var xs = CollectionsMarshal.AsSpan(literals);
var ys = CollectionsMarshal.AsSpan(other.literals);

if (xs.Length == ys.Length)
{
for (int i = 0; i < xs.Length; i++)
{
if (xs[i] != ys[i]) return false;
}
return true;
}

return false;
}
}
44 changes: 11 additions & 33 deletions src/ZLogger/Internal/ObjectPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,11 @@ internal sealed class ObjectPool<T>
int gate;
T? root;

#if USE_LIMIT_AND_SIZE
int size;
readonly int limit;

public ObjectPool(int limit)
{
this.limit = limit;
}

public int Size => size;
#endif

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPop([NotNullWhen(true)] out T? result)
{
// Instead of lock, use CompareExchange gate.
// In a worst case, missed cached object(create new one) but it's not a big deal.
// similar as ImmutableInterlocked
TRY_AGAIN:
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
{
var v = root;
Expand All @@ -44,46 +32,36 @@ public bool TryPop([NotNullWhen(true)] out T? result)
ref var nextNode = ref v.NextNode;
root = nextNode;
nextNode = null;
#if USE_LIMIT_AND_SIZE
size--;
#endif
result = v;
Volatile.Write(ref gate, 0);
return true;
}

Volatile.Write(ref gate, 0);
}
else
{
goto TRY_AGAIN;
}
result = default;
return false;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPush(T item)
{
TRY_AGAIN:
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
{
item.NextNode = root;
root = item;
Volatile.Write(ref gate, 0);
return true;

#if USE_LIMIT_AND_SIZE
if (size < limit)
{
item.NextNode = root;
root = item;
size++;
Volatile.Write(ref gate, 0);
return true;
}
else
{
Volatile.Write(ref gate, 0);
}
#endif
}
return false;
else
{
goto TRY_AGAIN;
}
}
}
}
2 changes: 1 addition & 1 deletion src/ZLogger/LogStates/InterpolatedStringLogState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal class InterpolatedStringLogState : IZLoggerFormattable, IReferenceCount
InterpolatedStringLogState()
{
this.magicalBoxStorage = new byte[1024];
this.parameters = new InterpolatedStringParameter[32];
this.parameters = new InterpolatedStringParameter[24];
}

public static InterpolatedStringLogState Create(int formattedCount)
Expand Down
74 changes: 56 additions & 18 deletions src/ZLogger/ZLoggerInterpolatedStringHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections;
using System.Collections.Concurrent;
using System.IO;
using System.IO.Hashing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -280,39 +281,76 @@ public LiteralList(List<string?> literals)
this.literals = literals;
}

#if NET8_0_OR_GREATER

// literals are all const string, in .NET 8 it is allocated in Non-GC Heap so can compare by address.
// https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#non-gc-heap
static ReadOnlySpan<byte> AsBytes(ReadOnlySpan<string?> literals)
{
return MemoryMarshal.CreateSpan(
ref Unsafe.As<string?, byte>(ref MemoryMarshal.GetReference(literals)),
literals.Length * Unsafe.SizeOf<string>());
}

public override int GetHashCode()
{
return unchecked((int)XxHash3.HashToUInt64(AsBytes(CollectionsMarshal.AsSpan(literals))));
}

public bool Equals(LiteralList other)
{
var xs = CollectionsMarshal.AsSpan(literals);
var ys = CollectionsMarshal.AsSpan(other.literals);

return AsBytes(xs).SequenceEqual(AsBytes(ys));
}

#else

[ThreadStatic]
static XxHash3? xxhash;

public override int GetHashCode()
{
var h = xxhash;
if (h == null)
{
h = xxhash = new XxHash3();
}
else
{
h.Reset();
}

var span = CollectionsMarshal.AsSpan(literals);
foreach (var item in span)
{
h.Append(MemoryMarshal.AsBytes(item.AsSpan()));
}

// https://github.com/Cyan4973/xxHash/issues/453
// XXH3 64bit -> 32bit, okay to simple cast answered by XXH3 author.
var source = AsBytes(span);
return unchecked((int)System.IO.Hashing.XxHash3.HashToUInt64(source));
return unchecked((int)h.GetCurrentHashAsUInt64());
}

public bool Equals(LiteralList other)
{
var xs = CollectionsMarshal.AsSpan(literals);
var ys = CollectionsMarshal.AsSpan(other.literals);

return AsBytes(xs).SequenceEqual(AsBytes(ys));
if (xs.Length == ys.Length)
{
for (int i = 0; i < xs.Length; i++)
{
if (xs[i] != ys[i]) return false;
}
return true;
}

return false;
}

// convert const strings as address sequence
static ReadOnlySpan<byte> AsBytes(ReadOnlySpan<string?> literals)
{
#if NETSTANDARD2_0
if (literals.IsEmpty)
return default;

return Shims.CreateSpan(
ref Unsafe.As<string?, byte>(ref Unsafe.AsRef(in literals[0])),
literals.Length * Unsafe.SizeOf<string>());
#else
return MemoryMarshal.CreateSpan(
ref Unsafe.As<string?, byte>(ref MemoryMarshal.GetReference(literals)),
literals.Length * Unsafe.SizeOf<string>());
#endif
}
}
}

Expand Down

0 comments on commit 0a69708

Please sign in to comment.