전체 GC에 그다지 영향을 미치지 않았으므로 결국에는 가비지없는 사전을 사용하지 않기로 결정했습니다.
기록을 위해 다음은 가비지없는 사전의 구현입니다. 배고픈 기억이지만 잘 돌아 간다.
잠재적 정수 키에 충분한 슬롯을 사용하여 새 사전을 인스턴스화합니다. 키가 20 만에서 25 만까지 다양 할 수 있다면
이
MyIntegerKeyDictionary = new MyIntegerKeyDictionary<int, MyClass>(50000);
, 50,000 잠재력을 인스턴스화 : 당신이 그것을 인스턴스화 할 때 예를 들어, 기본 정수 키가 0과 50000 사이의 범위 수 있다면, 당신은 5 만 합격해야합니다 키를 누르면 자동으로 "리베이스 (rebase)"되어 첫 번째 키를 기준으로 200,000에서 250,000까지의 범위를 가질 수 있습니다.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MyLogType;
namespace MyHelper
{
/// <summary>
/// NOTE: Non thread safe, only run this individually.
/// </summary>
/// <typeparam name="T">Type of item we are adding to the dictionary.</typeparam>
public class MyIntegerKeyDictionary<T> where T : class
{
/// <summary>
/// Array in which we store the entries.
/// </summary>
volatile private T[] ArrayToUse;
/// <summary>
/// Allows us to check the maximum size, just in case.
/// </summary>
private readonly int SizeInternal;
/// <summary>
/// Keeps track of the current number of items in the dictionary.
/// </summary>
public int Count = 0;
/// <summary>
/// Base number. For numbers that start with a huge base, this allows the index to work without allocating megabytes of memory.
/// </summary>
private int BaseNumberToAdd { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="Size">Size of the dictionary.</param>
public MyIntegerKeyDictionary(int Size)
{
// Create the array to hold n number of items.
ArrayToUse = new T[Size];
// We must touch all of these entries, to force page faults now (rather than later).
for (int i = 0; i < ArrayToUse.Length; i++)
{
ArrayToUse[i] = null;
}
BaseNumberToAdd = int.MinValue;
this.SizeInternal = Size;
}
/// <summary>
/// Add an item.
/// </summary>
/// <param name="Key">Key.</param>
/// <param name="Value">Value.</param>
/// <returns>True if the item was added, false if not.</returns>
public bool TryAdd(int Key, T Value)
{
if (BaseNumberToAdd == int.MinValue)
{
BaseNumberToAdd = Key;
//Console.Write(string.Format("{0}Message W20120907-3751. TryAdd. Adding first item {1}.\n",
//MyLog.NPrefix(), Key));
}
Key = Key - BaseNumberToAdd;
if (Key < 0)
{
Console.Write(string.Format("{0}Warning W20120907-3750. TryAdd. Attempted to add a key with index {1} which is < 0.\n",
MyLog.NPrefix(), Key));
return false;
}
if (Key >= this.SizeInternal)
{
Console.Write(string.Format("{0}Warning W20120907-3756. TryAdd. Attempted to add a key with index {1} which is > max {2}\n",
MyLog.NPrefix(), Key, this.SizeInternal));
return false;
}
if (ArrayToUse[Key] == null)
{
Interlocked.Increment(ref Count);
}
ArrayToUse[Key] = Value;
return true;
}
/// <summary>
/// Remove an item from the dictionary.
/// </summary>
/// <param name="Key">Key that we want to remove.</param>
/// <returns>True if the item could be removed, false if not.</returns>
public bool TryRemove(int Key)
{
if (BaseNumberToAdd == int.MinValue)
{
Console.Write(string.Format("{0}Warning W20120907-8756. TryRemove. Attempted to remove an item without any items in the dictionary yet {1}.\n",
MyLog.NPrefix(), Key));
return false;
}
Key = Key - BaseNumberToAdd;
if (Key < 0)
{
Console.Write(string.Format("{0}Warning W20120907-9756. TryRemove. Attempted to remove a key with index {1} which is < 0.\n",
MyLog.NPrefix(), Key));
return false;
}
if (Key >= this.SizeInternal)
{
Console.Write(string.Format("{0}Warning W20120907-6756. TryRemove. Attempted to remove a key with index {1} which is > max {2}\n",
MyLog.NPrefix(), Key, this.SizeInternal));
return false;
}
if (ArrayToUse[Key] != null)
{
Interlocked.Decrement(ref Count);
}
ArrayToUse[Key] = null;
return true;
}
/// <summary>
/// Indexer.
/// </summary>
/// <param name="key">Key.</param>
/// <returns>Value.</returns>
public T this[int key]
{
get
{
T valueToReturn;
TryGetValue(key, out valueToReturn);
return valueToReturn;
}
}
/// <summary>
/// Attempt to get the value.
/// </summary>
/// <param name="Key">Key.</param>
/// <param name="Value">Value.</param>
/// <returns>True if the value exists, false if not.</returns>
public bool TryGetValue(int Key, out T Value)
{
Value = null;
if (BaseNumberToAdd == int.MinValue)
{
Console.Write(string.Format("{0}Warning W20120907-8756. TryGetValue. Attempted to retrieve an item without any items in the dictionary yet {1}.\n",
MyLog.NPrefix(), Key));
return false;
}
Key = Key - BaseNumberToAdd;
if (ArrayToUse[Key] == null)
{
return false;
}
Value = ArrayToUse[Key];
return true;
}
/// <summary>
/// Checks to see if the key exists.
/// </summary>
/// <param name="Key">Key index.</param>
/// <returns>True if the item exists, false if not.</returns>
public bool ContainsKey(int Key)
{
if (Key == 0)
{
Console.Write(string.Format("{0}Warning W20120907-1914. ContainsKey. Have not rebased yet. Ignoring query for ContainsKey(0).\n",
MyLog.NPrefix()));
return false;
}
if (BaseNumberToAdd == int.MinValue)
{
Console.Write(string.Format("{0}Warning W20120907-8756. ContainsKey. Attempted to check if Key {1} exists, however BaseNumber is not set yet.\n",
"", Key));
return false;
}
Key = Key - BaseNumberToAdd;
if (Key < 0)
{
Console.Write(string.Format("{0}Warning W20120907-8756. ContainsKey. Key = {1} which is < 0.\n",
"", Key));
return false;
}
if (Key >= this.SizeInternal)
{
MyLogAsync.LogWarning(string.Format("{0}Warning W20120907-5756. ContainsKey. Key({1}) >= this.SizeInternal ({2}).\n",
MyLog.NPrefix(), Key, this.SizeInternal));
return false;
}
if (ArrayToUse[Key] == null)
{
return false;
}
return true;
}
/*
private bool CheckKeyBounds(int Key, string description)
{
if (Key < 0)
{
MyLogAsync.LogWarning(string.Format("{0}Warning W20120907-8756. {1}. Attempted to add a key with index {2} which is < 0.\n",
MyLog.NPrefix(), description, Key));
}
if (Key >= this.SizeInternal)
{
MyLogAsync.LogWarning(string.Format("{0}Warning W20120907-5756. {1}. Attempted to add a key with index {2} which is > max {3}\n",
MyLog.NPrefix(), description, Key, this.SizeInternal));
return false;
}
}
*/
}
}
용량이 10,000 인'Dictionary' 생성자를 사용해 보셨습니까? http://msdn.microsoft.com/en-us/library/tk84bxf4.aspx –
TKey 및 TValue는 무엇이며 일반 API 또는 일반이 아닌 API를 사용하여 액세스하고 있습니까? –
사전은 O (로그 N) 비율로 증가합니다. 요소의 양을 미리 정의하면 가비지 수집 문제를 해결하는 데 도움이 될 것입니다. 이러한 문제가 발생하면 전략을 재검토하는 것이 좋습니다. 너무 많은 사전 인스턴스를 할당하는 것이 정말로 필요합니까? – Polity