Dictionary CPU 100%


  昨天服務器的CPU突然100%,此服務已經運行幾年了,都平安無事。既然問題出現當然要找出這個遺留多年的小概率問題。出現cpu 100% 一般就是哪里出現了無法跳出的死循環。

  1、獲取進程的內存信息

  服務器使用的window server 直接右鍵創建轉儲文件即可。這個直接點點的方式是使用window server最方便的地方(^_^)。

  2、加載內存文件信息

  將文件復制本地,直接拖拽到windbg中。(windbg直接在window 應用商店下載即可)

  

 

  3、獲取進程內耗時線程

  在0:000 輸入框中輸入!runaway 敲回車,獲取線程占用cpu時間

  

 

   

   4、獲取線程的棧信息

  從cpu的線程占用時間來看,線程64,89,96,95,90占用的時間最長,可以初步斷定問題就出現在這幾個線程中。輸入:~64s進入該線程(64代表的是線程id)

  

  進入該線程后就可以加載線程的棧信息了,在命令框中輸入!CLRStack 。如果出現圖示信息說明需要單獨加載SOS.dll 文件。使用everything軟件全局搜索該dll文件位置,然后在輸入框中:.load 全路徑\SOS.dll。加載完成再次輸入:!CLRStack 就可以正常顯示棧信息了。

  

  5、問題定位

  從棧信息來看,線程一直停留在:System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)這個方法里面,調用這個方法的類是:Aop.Api.Parser.AopJsonParser,這個類是支付寶官方sdk中的。先看FindEntry這個方法干了啥。直接官網查看源碼:

  

private int FindEntry(TKey key) {
            if( key == null) {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
            }
 
            if (buckets != null) {
                int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
                for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
                    if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
                }
            }
            return -1;
        }

  從源碼來就是判斷key是否存在,看來就是死循環for里面了。再來看這個dictionary是用來干啥了的,反編譯Aop dll文件

 

private static Dictionary<string, AopAttribute> GetAopAttributes(Type type)
{
    Dictionary<string, AopAttribute> dictionary = null;
    if (!AopJsonParser<T>.attrs.TryGetValue(type.FullName, out dictionary) || (dictionary == null))
    {
        dictionary = new Dictionary<string, AopAttribute>();
private static readonly Dictionary<string, Dictionary<string, AopAttribute>> attrs;
 

 

  從源碼可以看見定義了一個靜態Dictionary attrs變量,既然是靜態變量,會出現多線程競爭問題。官網也明確說明Dictionary 是非線程安全的,如果多線程讀寫需要自己去寫程序保證線程安全或者使用ConcurrentDictionary。

  6、問題

  問題的根本原因是多線程多寫非線程安全Dictionary,導致在FindEntry方法死循環。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM