Skip to content

Commit

Permalink
Add logging of cache size (#27288)
Browse files Browse the repository at this point in the history
* Add logging of cache size

* Remove unused method

* Fix

* Cache total length
  • Loading branch information
JoshLove-msft authored Mar 2, 2022
1 parent 61bd190 commit 095b9c7
Show file tree
Hide file tree
Showing 10 changed files with 503 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -1,70 +1,84 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections;
using System.Collections.Generic;

namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro
{
/// <summary>
/// A simple LRU cache implementation using a doubly linked list and dictionary.
/// </summary>
/// <typeparam name="K">The type of key</typeparam>
/// <typeparam name="V">The type of value</typeparam>
internal class LruCache<K,V>
/// <typeparam name="TKey">The type of key</typeparam>
/// <typeparam name="TValue">The type of value</typeparam>
internal class LruCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private readonly int _capacity;
private readonly LinkedList<KeyValuePair<K, V>> _linkedList;
private readonly Dictionary<K, LinkedListNode<KeyValuePair<K, V>>> _map;
private readonly LinkedList<KeyValuePair<TKey, TValue>> _linkedList;
private readonly Dictionary<TKey, (LinkedListNode<KeyValuePair<TKey, TValue>> Node, int Length)> _map;
private readonly object _syncLock;

internal int Count => _linkedList.Count;

internal int TotalLength { get; private set; }

public LruCache(int capacity)
{
_capacity = capacity;
_linkedList = new LinkedList<KeyValuePair<K, V>>();
_map = new Dictionary<K, LinkedListNode<KeyValuePair<K, V>>>();
_linkedList = new LinkedList<KeyValuePair<TKey, TValue>>();
_map = new Dictionary<TKey, (LinkedListNode<KeyValuePair<TKey, TValue>>, int)>();
_syncLock = new object();
}

public bool TryGet(K key, out V value)
public bool TryGet(TKey key, out TValue value)
{
lock (_syncLock)
{
if (_map.TryGetValue(key, out var node))
if (_map.TryGetValue(key, out var mapValue))
{
var node = mapValue.Node;
value = node.Value.Value;
_linkedList.Remove(node);
_linkedList.AddFirst(node);
return true;
}

value = default(V);
value = default(TValue);
return false;
}
}

public void AddOrUpdate(K key, V val)
public void AddOrUpdate(TKey key, TValue val, int length)
{
lock (_syncLock)
{
if (_map.TryGetValue(key, out var existingNode))
if (_map.TryGetValue(key, out var existingValue))
{
// remove node - we will re-add a new node for this key at the head of the list, as the value may be different
_linkedList.Remove(existingNode);
_linkedList.Remove(existingValue.Node);
TotalLength -= _map[key].Length;
}

// add new node
var node = new LinkedListNode<KeyValuePair<K, V>>(new KeyValuePair<K, V>(key, val));
var node = new LinkedListNode<KeyValuePair<TKey, TValue>>(new KeyValuePair<TKey, TValue>(key, val));
_linkedList.AddFirst(node);
_map[key] = node;
_map[key] = (node, length);
TotalLength += length;

if (_map.Count > _capacity)
{
// remove least recently used node
LinkedListNode<KeyValuePair<K, V>> last = _linkedList.Last;
LinkedListNode<KeyValuePair<TKey, TValue>> last = _linkedList.Last;
_linkedList.RemoveLast();
var toRemove = _map[last.Value.Key];
_map.Remove(last.Value.Key);
TotalLength -= toRemove.Length;
}
}
}

public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _linkedList.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<!-- Shared source from Azure.Core -->
<ItemGroup>
<Compile Include="$(AzureCoreSharedSources)AppContextSwitchHelper.cs" LinkBase="Shared" />
<Compile Include="$(AzureCoreSharedSources)AzureEventSource.cs" LinkBase="Shared" />
<Compile Include="$(AzureCoreSharedSources)ContentTypeUtilities.cs" LinkBase="Shared" />
<Compile Include="$(AzureCoreSharedSources)DiagnosticScope.cs" LinkBase="Shared" />
<Compile Include="$(AzureCoreSharedSources)TaskExtensions.cs" LinkBase="Shared" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Diagnostics.Tracing;
using Avro;
using Azure.Core.Diagnostics;

namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro
{
/// <summary>
/// Serves as an ETW event source for logging of information about
/// Entity's client.
/// </summary>
///
/// <remarks>
/// When defining Start/Complete tasks, it is highly recommended that the
/// the CompleteEvent.Id must be exactly StartEvent.Id + 1.
/// </remarks>
[EventSource(Name = EventSourceName)]
internal class SchemaRegistryAvroEventSource : AzureEventSource
{
/// <summary>The name to use for the event source.</summary>
private const string EventSourceName = "Microsoft-Azure-Data-SchemaRegistry-ApacheAvro";

internal const int CacheUpdatedEvent = 1;

/// <summary>
/// Provides a singleton instance of the event source for callers to
/// use for logging.
/// </summary>
public static SchemaRegistryAvroEventSource Log { get; } = new SchemaRegistryAvroEventSource();

/// <summary>
/// Prevents an instance of the <see cref="SchemaRegistryAvroEventSource"/> class from being
/// created outside the scope of the <see cref="Log" /> instance, as well as setting up the
/// integration with AzureEventSourceListener.
/// </summary>
protected SchemaRegistryAvroEventSource() : base(EventSourceName)
{
}

[NonEvent]
public virtual void CacheUpdated(LruCache<string, Schema> idToSchemaCache, LruCache<Schema, string> schemaToIdCache)
{
if (IsEnabled())
{
CacheUpdatedCore(idToSchemaCache.Count + schemaToIdCache.Count, idToSchemaCache.TotalLength + schemaToIdCache.TotalLength);
}
}

[Event(CacheUpdatedEvent, Level = EventLevel.Verbose, Message = "Cache entry added or updated. Total number of entries: {0}; Total schema length: {1}")]
public virtual void CacheUpdatedCore(int entryCount, int totalSchemaLength)
{
if (IsEnabled())
{
WriteEvent(CacheUpdatedEvent, entryCount, totalSchemaLength);
}
}
}
}
Loading

0 comments on commit 095b9c7

Please sign in to comment.