gpt4 book ai didi

公司某资料子系统定期cpu过高的诊断

转载 作者:我是一只小鸟 更新时间:2023-03-06 14:31:24 27 4
gpt4 key购买 nike

背景

公司里的某负责保存用户文档的子系统有时会忽然cpu很高,过了大约5分钟后又恢复正常水平。领导协调让我帮看一下 (我心里是: 不熟悉这个子系统里面的代码,我尽力哈 😓 ) 。

其实确实是这样的,如果熟悉出问题的系统的代码,会对诊断问题起到很大的帮助,否则就需要更多的利用对底层的理解了.

分析

打听后知道了这个子系统用.net core写的,可以运行在windows和linux docker上,且这次的cpu高的问题,他们在windows运行也可复现。于是,我让他们在windows上运行,发现cpu高的时候dump一下。(然后windbg就可以准备下地 干活了 😖 ) 。

在用windbg看了大部分threadpool worker线程的情况后,我发现大部分线程都运行到这样类似的call stack上

先大概看一下这个 PeopleManagementService.Program+c__DisplayClass2_0.b__0(PeopleManagementService.User) 在做什么,用IL反编译工具可以看到

再结合call stack,感觉上下文正在从某集合里查找东西呢?(一个题外话,上面那个 c__DisplayClass2_0.b__0 名字挺奇怪,其实这是C# compiler在build我们的C#代码到IL时帮着生成的一些code。对于目前这个,就对应我们C#程序员写出的 lambda  ) 。

找东西会把cpu明显提高么?去看看 PrintUserLastEnteredTimeDetail() 在干什么吧。(其实子系统team的同事人很好,所以这次我直接找他要对应的代码得 了 👦 )  简化代码:

 看起来是在一个叫 users 的List中按条件查找东西。看看这个list的size, 用 !do 试一下:

                          
                             1
                          
                          
                            0
                          
                          :
                          
                            027
                          
                          > !DumpObj /
                          
                            d 0000019a8000d938

                          
                          
                             2
                          
                           Name:        System.Collections.Generic.List`
                          
                            1
                          
                          
                            [[PeopleManagementService.User, PeopleManagementService]]

                          
                          
                             3
                          
                          
                            MethodTable: 00007ff96c313e88

                          
                          
                             4
                          
                          
                            EEClass:     00007ff96c2df530

                          
                          
                             5
                          
                           Tracked Type: 
                          
                            false
                          
                          
                             6
                          
                           Size:        
                          
                            32
                          
                          (
                          
                            0x20
                          
                          
                            ) bytes

                          
                          
                             7
                          
                           File:        C:\Program Files\dotnet\shared\Microsoft.NETCore.App\
                          
                            6.0
                          
                          .
                          
                            14
                          
                          
                            \System.Private.CoreLib.dll

                          
                          
                             8
                          
                          
                            Fields:

                          
                          
                             9
                          
                          
                                          MT    Field   Offset                 Type VT     Attr            Value Name

                          
                          
                            10
                          
                           00007ff96c2fd618  
                          
                            4002099
                          
                          
                            8
                          
                               System.__Canon[]  
                          
                            0
                          
                          
                             instance 0000019a90bc12a0 _items

                          
                          
                            11
                          
                           00007ff96c2a94b0  400209a       
                          
                            10
                          
                                   System.Int32  
                          
                            1
                          
                           instance           
                          
                            524288
                          
                          
                             _size

                          
                          
                            12
                          
                           00007ff96c2a94b0  400209b       
                          
                            14
                          
                                   System.Int32  
                          
                            1
                          
                           instance           
                          
                            524288
                          
                          
                             _version

                          
                          
                            13
                          
                           00007ff96c2fd618  400209c        
                          
                            8
                          
                               System.__Canon[]  
                          
                            0
                          
                          
                            static
                          
                          
                            dynamic
                          
                           statics NYI                 s_emptyArray
                        
size大约 524288 ,500K的items在list里面,然后多个线程在一起进行这样的查找,所以cpu提高了。

后记

在告知同事这个原因前,我还有意无意地查了一下那个保存big list的Dictionary,用 !gcroot

 然后 !do 看一下:

                            
                              1
                            
                             !
                            
                              do
                            
                            
                               0000019A8000D818

                            
                            
                              2
                            
                             Name:        System.Collections.Generic.Dictionary`
                            
                              2
                            
                            +Entry[[System.String, System.Private.CoreLib],[System.Collections.Generic.List`
                            
                              1
                            
                            
                              [[PeopleManagementService.User, PeopleManagementService]], System.Private.CoreLib]][]

                            
                            
                              3
                            
                            
                              MethodTable: 00007ff96c322808

                            
                            
                              4
                            
                            
                              EEClass:     00007ff96c322770

                            
                            
                              5
                            
                             Tracked Type: 
                            
                              false
                            
                            
                              6
                            
                             Size:        
                            
                              96
                            
                            (
                            
                              0x60
                            
                            
                              ) bytes

                            
                            
                              7
                            
                             Array:       Rank 
                            
                              1
                            
                            , Number of elements 
                            
                              3
                            
                            , Type VALUETYPE
                          
一个保存着那么大list的Dictionary, 其实只有<=3的key value pairs。再看看它的keys是啥。我们用 windbg 的memory view直接看内存中的"瓤"吧:

64位的进程运行环境,clr array的第一个item在 0000019A8000D818 + 8(mt ptr size) + 4(length field) + 4 (padding) ,所以看标红的那两个地址.

                                
                                  1
                                
                                
                                  0
                                
                                :
                                
                                  027
                                
                                > !DumpObj /
                                
                                  d 0000019a8000cce8

                                
                                
                                  2
                                
                                
                                  Name:        System.String

                                
                                
                                  3
                                
                                
                                  MethodTable: 00007ff96c2bd708

                                
                                
                                  4
                                
                                
                                  EEClass:     00007ff96c299d60

                                
                                
                                  5
                                
                                 Tracked Type: 
                                
                                  false
                                
                                
                                  6
                                
                                 Size:        
                                
                                  30
                                
                                (
                                
                                  0x1e
                                
                                
                                  ) bytes

                                
                                
                                  7
                                
                                 File:        C:\Program Files\dotnet\shared\Microsoft.NETCore.App\
                                
                                  6.0
                                
                                .
                                
                                  14
                                
                                
                                  \System.Private.CoreLib.dll

                                
                                
                                  8
                                
                                 String:      Male
                              
                                
                                  1
                                
                                
                                  0
                                
                                :
                                
                                  027
                                
                                > !DumpObj /
                                
                                  d 0000019a8000cd08

                                
                                
                                  2
                                
                                
                                  Name:        System.String

                                
                                
                                  3
                                
                                
                                  MethodTable: 00007ff96c2bd708

                                
                                
                                  4
                                
                                
                                  EEClass:     00007ff96c299d60

                                
                                
                                  5
                                
                                 Tracked Type: 
                                
                                  false
                                
                                
                                  6
                                
                                 Size:        
                                
                                  34
                                
                                (
                                
                                  0x22
                                
                                
                                  ) bytes

                                
                                
                                  7
                                
                                 File:        C:\Program Files\dotnet\shared\Microsoft.NETCore.App\
                                
                                  6.0
                                
                                .
                                
                                  14
                                
                                
                                  \System.Private.CoreLib.dll

                                
                                
                                  8
                                
                                 String:      Female
                              

原来Dictionary按性别分类保存了所有的用户信息.

我把这些信息告诉同事,他第一反应是没有想到这个运行的结果。按照他的代码,他预期是按性别和用户名一起来当key,然后放到Dictionary,这样查询起来至少时间复杂度不应这么高。于是我和那个同事打开相关的生成key的代码:

                                  
                                    1
                                  
                                  
                                    private
                                  
                                  
                                    static
                                  
                                  
                                    string
                                  
                                   GetUserKey(Gender gender, 
                                  
                                    string
                                  
                                   userName) => 
                                  
                                    string
                                  
                                  .Join(userName, gender);
                                
大家发现没?想当然的用String.Join来连接2个object,却没注意其实String.Join的定义是这样,注意第一个参数可是 separator 啊:

这么错误的使用,就相当于把user name作为separator,而后面的集合参数其实就传了一个性别,所以生成的key就总是同一个,本想做成user cache的Dictionary的数据最终退化为两个很大的lists 😓 然后多个线程一起在这两个大大的list上以O(n)的时间复杂度查找东西,cpu就高起来了…… 。

总结

看来大家不能这么随随便便的写C#代码啊,虽然.net sdk会为C#程序员提供便利和安全性,但自己也不该想当然的无脑coding哈。最后同事的脸比较红哈 🙈

最后此篇关于公司某资料子系统定期cpu过高的诊断的文章就讲到这里了,如果你想了解更多关于公司某资料子系统定期cpu过高的诊断的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com