簡體   English   中英

多個線程減慢了整個字典訪問速度?

[英]Multiple threads slowing down overall dictionary access?

我正在分析一個C#應用程序,它看起來像兩個線程,每個調用Dictionary<>.ContainsKey() 5000個時間,每個在兩個單獨但相同的字典(只有兩個項目)上,是一個調用Dictionary<>.ContainsKey()一個線程的兩倍慢Dictionary<>.ContainsKey()在單個詞典上10000次。

我正在使用名為JetBrains dotTrace的工具測量“線程時間”。 我明確使用相同數據的副本,因此我沒有使用同步原語。 .NET是否可能在幕后進行一些同步?

我有一個雙核機器,有三個線程在運行:一個是使用Semaphore.WaitAll()阻塞,而工作是在兩個新線程上完成的,這兩個新線程的優先級設置為ThreadPriority.Highest

已經排除了明顯的罪魁禍首,例如並沒有實際並行運行代碼,也沒有使用發布版本。

編輯:

人們想要代碼。 好吧那么:

    private int ReduceArrayIteration(VM vm, HeronValue[] input, int begin, int cnt)
    {
        if (cnt <= 1)
            return cnt;

        int cur = begin;

        for (int i=0; i < cnt - 1; i += 2)
        {
            // The next two calls are effectively dominated by a call 
            // to dictionary ContainsKey
            vm.SetVar(a, input[begin + i]);
            vm.SetVar(b, input[begin + i + 1]);
            input[cur++] = vm.Eval(expr);
        }

        if (cnt % 2 == 1)
        {
            input[cur++] = input[begin + cnt - 1];
        }

        int r = cur - begin;
        Debug.Assert(r >= 1);
        Debug.Assert(r < cnt);
        return r;
    }

    // From VM
    public void SetVar(string s, HeronValue o)
    {
        Debug.Assert(o != null);
        frames.Peek().SetVar(s, o);
    }

    // From Frame
    public bool SetVar(string s, HeronValue o)
    {
        for (int i = scopes.Count; i > 0; --i)
        {
            // Scope is a derived class of Dictionary
            Scope tbl = scopes[i - 1];
            if (tbl.HasName(s))
            {
                tbl[s] = o;
                return false;
            }
        }
        return false;
    }

現在這里是線程產生代碼,可能會被延遲:

public static class WorkSplitter
{
    static WaitHandle[] signals;

    public static void ThreadStarter(Object o)
    {
        Task task = o as Task;
        task.Run();
    }

    public static void SplitWork(List<Task> tasks)
    {
        signals = new WaitHandle[tasks.Count];
        for (int i = 0; i < tasks.Count; ++i)
            signals[i] = tasks[i].done;
        for (int i = 0; i < tasks.Count; ++i)
        {
            Thread t = new Thread(ThreadStarter);
            t.Priority = ThreadPriority.Highest;
            t.Start(tasks[i]);
        }
        Semaphore.WaitAll(signals);
    }        
}

即使在Dictionary中有任何鎖定(沒有),它也不會影響你的測量,因為每個線程都使用一個單獨的。 運行此測試10,000次不足以獲得可靠的計時數據,ContainsKey()只需要20納秒左右。 您至少需要幾百萬次才能避免調度工件。

暫無
暫無

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

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