簡體   English   中英

如何可靠地測試/確定.Net HashSet的大小(包括空存儲桶) <T> 賓語?

[英]How can I reliably test/benchmark the size (including empty buckets) of a .Net HashSet<T> object?

作為個人教育和實驗中的一項練習 ,我想創建自己的HashTable類。 具體來說,我想編寫該對象,而不使用任何現有代碼(即,該對象將不會從另一個類繼承),而是為了測試目的而映射到現有接口。

由於我打算用C#編寫代碼,因此我的“基准”將是.Net HashSet<T>類。 我可以輕松地針對添加,刪除和查找請求的執行時間進行測試,但是我不知道如何測試HashSet基准對象的大小, 包括將來用於添加請求的所有存儲桶都為空

HashSet<t>對象動態增長以為將來的插入騰出空間時,如何跟蹤它的大小?

需要明確的是,我不需要知道確切的字節數(我知道.Net框架使得很難獲得許多類型的對象的確切大小),但是我寧願知道如何我執行各種類型的測試時,正在使用許多存儲桶,有多少存儲桶正在等待使用。

獲取桶的數量和大小的最佳方法是使用反射。 唯一的麻煩是您需要首先了解集合的行為。 稍微閱讀一下代碼並進行一些嘗試和錯誤之后,似乎您需要計算私有m_buckets數組的大小以獲取存儲桶數,並計算大於0的值的數目以獲取已使用存儲桶的數。 該方法如下所示:

static void CountBuckets<T>(HashSet<T> hashSet)
{
    var field = typeof(HashSet<T>).GetField("m_buckets", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

    var buckets = (int[])field.GetValue(hashSet);

    int numberOfBuckets = 0;
    int numberOfBucketsUsed = 0;

    if (buckets != null)
    {
        numberOfBuckets = buckets.Length;
        numberOfBucketsUsed = buckets.Where(i => i != 0).Count();
    }

    Console.WriteLine("Number of buckets: {0} / Used: {1}", numberOfBuckets, numberOfBucketsUsed);
}

為了測試它,我首先創建了一個自定義類,可以在其中手動設置哈希碼:

public class Hash
{
    private readonly int hashCode;

    public Hash(int hashCode)
    {
        this.hashCode = hashCode;
    }

    public override int GetHashCode()
    {
        return this.hashCode;
    }
}

從那里,我做了一些測試:

    var hashSet = new HashSet<Hash>();

    CountBuckets(hashSet);
    // Number of buckets: 0 / Used: 0

    var firstHash = new Hash(0);

    hashSet.Add(firstHash);

    CountBuckets(hashSet);
    // Number of buckets: 3 / Used: 1

    hashSet.Add(new Hash(1));
    hashSet.Add(new Hash(2));

    CountBuckets(hashSet);
    // Number of buckets: 3 / Used: 3

    hashSet.Add(new Hash(3));

    CountBuckets(hashSet);
    // Number of buckets: 7 / Used: 4

    hashSet.Add(new Hash(1));

    CountBuckets(hashSet);
    // Number of buckets: 7 / Used: 4

    hashSet.Remove(firstHash);

    CountBuckets(hashSet);
    // Number of buckets: 7 / Used: 3

這聽起來與直觀行為一致。 首先,存儲桶的數量為0。添加一個元素后,其數量將擴展為3。存儲桶的數量保持穩定,直到添加了第四個元素,並將計數擴展為7。在模擬哈希沖突時,已使用存儲桶的數量保持不變如預期的那樣穩定。 刪除元素會減少使用的存儲桶數量。

我對HashSet內部不是很熟悉,但是您可以看到其來源並使用Reflection獲取其內部值:

HashSet<int> hashSet = new HashSet<int>();
var countField = typeof(HashSet<int>).GetField("m_count", BindingFlags.NonPublic | BindingFlags.Instance);
var freeListField = typeof(HashSet<int>).GetField("m_freeList", BindingFlags.NonPublic | BindingFlags.Instance);
var count = countField.GetValue(hashSet);
var freeList = freeListField.GetValue(hashSet);

注意:這種對私有成員訪問權限的侵犯當然非常丑陋,但是我認為在您的開發/測試階段可以接受。

這是一個有趣的問題強文本...我對你有個根本性的建議:

啟動您的應用程序並獲取內存的大小,然后再初始化HashSet。 您可以使用Process.GetCurrentProcess()。WorkingSet64 (在msdn上: http//msdn.microsoft.com/zh-cn/library/system.diagnostics.process.workingset64 (v = vs.110.aspx )上進行操作

然后填充您的HashSet並再次打印Process.GetCurrentProcess()。WorkingSet64。 不同之處在於您要尋找的尺寸。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM