国产睡熟迷奷白丝护士系列精品,中文色字幕网站,免费h网站在线观看的,亚洲开心激情在线

      <sup id="hb9fh"></sup>
          1. 千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

            手機(jī)站
            千鋒教育

            千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

            千鋒教育

            掃一掃進(jìn)入千鋒手機(jī)站

            領(lǐng)取全套視頻
            千鋒教育

            關(guān)注千鋒學(xué)習(xí)站小程序
            隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

            當(dāng)前位置:首頁  >  技術(shù)干貨  > Python性能分析

            Python性能分析

            來源:千鋒教育
            發(fā)布人:xqq
            時(shí)間: 2023-11-07 19:23:11 1699356191

            python標(biāo)準(zhǔn)庫提供兩個(gè)代碼性能分析相關(guān)的模塊,即timeit和cProfile/profile。前者更適合測試簡短的代碼片段,后者則可分析代碼片段乃至整體模塊中各個(gè)函數(shù)的調(diào)用次數(shù)、運(yùn)行耗時(shí)等信息。

            cProfile是profile的C版本,開銷更小。基于cProfile模塊,可方便地評估程序性能瓶頸(bottleneck),借以發(fā)現(xiàn)程序中值得優(yōu)化的短板。

            根據(jù)粒度不同,可將cProfile使用場景分為三類。

            1.1分析單條語句

            importcProfile,pstats,re,cStringIO

            cProfile.run('re.compile("foo|bar")','prfRes')#將cProfile的結(jié)果寫入prfRes文件

            p=pstats.Stats('prfRes')#pstats讀取cProfile輸出結(jié)果

            #strip_dirs()剝除模塊名的無關(guān)路徑(如C:\Python27\lib\)

            #sort_stats('cumtime')或sort_stats('cumulative')按照cumtime對打印項(xiàng)排序

            #print_stats(n)打印輸出前10行統(tǒng)計(jì)項(xiàng)(不指定n則打印所有項(xiàng))

            p.strip_dirs().sort_stats('cumtime').print_stats(5)

            pstats模塊可用多種方式對cProfile性能分析結(jié)果進(jìn)行排序并輸出。運(yùn)行結(jié)果如下:

            TueMay2413:56:072016prfRes

            195functioncalls(190primitivecalls)in0.001seconds

            Orderedby:cumulativetime

            Listreducedfrom33to5duetorestriction<5>

            ncallstottimepercallcumtimepercallfilename:lineno(function)

            10.0000.0000.0010.001:1()

            10.0000.0000.0010.001re.py:192(compile)

            10.0000.0000.0010.001re.py:230(_compile)

            10.0000.0000.0010.001sre_compile.py:567(compile)

            10.0000.0000.0000.000sre_compile.py:552(_code)

            其中,tottime表示某函數(shù)的總計(jì)運(yùn)行時(shí)間(不含該函數(shù)內(nèi)調(diào)用的子函數(shù)運(yùn)行時(shí)間),cumtime表示某函數(shù)及其調(diào)用的子函數(shù)的累積運(yùn)行時(shí)間。

            1.2分析代碼片段

            pr=cProfile.Profile()

            pr.enable()#以下為待分析代碼段

            regMatch=re.match('^([^/]*)/(/|\*)+(.*)$','//*suspicious')

            printregMatch.groups()

            pr.disable()#以上為待分析代碼段

            s=cStringIO.StringIO()

            pstats.Stats(pr,stream=s).sort_stats('cumulative').print_stats(10)

            prints.getvalue()

            運(yùn)行結(jié)果如下:

            ('','*','suspicious')

            536functioncalls(512primitivecalls)in0.011seconds

            Orderedby:cumulativetime

            Listreducedfrom78to10duetorestriction<10>

            ncallstottimepercallcumtimepercallfilename:lineno(function)

            20.0000.0000.0090.005C:\Python27\lib\idlelib\PyShell.py:1343(write)

            20.0000.0000.0090.005C:\Python27\lib\idlelib\rpc.py:591(__call__)

            20.0000.0000.0090.005C:\Python27\lib\idlelib\rpc.py:208(remotecall)

            20.0000.0000.0090.004C:\Python27\lib\idlelib\rpc.py:238(asyncreturn)

            20.0000.0000.0090.004C:\Python27\lib\idlelib\rpc.py:279(getresponse)

            20.0000.0000.0090.004C:\Python27\lib\idlelib\rpc.py:295(_getresponse)

            20.0000.0000.0090.004C:\Python27\lib\threading.py:309(wait)

            80.0090.0010.0090.001{method'acquire'of'thread.lock'objects}

            10.0000.0000.0020.002C:\Python27\lib\re.py:138(match)

            10.0000.0000.0020.002C:\Python27\lib\re.py:230(_compile)

            1.3分析整個(gè)模塊

            使用命令行,調(diào)用cProfile腳本分析其他腳本文件。命令格式為:

            python-mcProfile[-ooutput_file][-ssort_order]myscript.py

            注意,-o和-s選項(xiàng)不可同時(shí)使用。

            以C代碼統(tǒng)計(jì)工具為例,運(yùn)行如下命令:

            E:\PyTest>python-mcProfile-stottimeCLineCounter.pysource-d-b>out.txt

            截取out.txt文件部分內(nèi)容如下:

            250316245433620.25xtm_mgr.c

            1408729374932093169380.26

            762068functioncalls(762004primitivecalls)in2.967seconds

            Orderedby:internaltime

            ncallstottimepercallcumtimepercallfilename:lineno(function)

            820.9850.0122.8690.035CLineCounter.py:11(CalcLines)

            1176400.6120.0001.3150.000re.py:138(match)

            1176500.3810.0000.3810.000{method'match'of'_sre.SRE_Pattern'objects}

            1176550.3190.0000.3240.000re.py:230(_compile)

            1380500.1980.0000.1980.000{method'isspace'of'str'objects}

            1058230.1650.0000.1650.000{method'strip'of'str'objects}

            123156/1231410.1540.0000.1540.000{len}

            378870.0550.0000.0550.000{method'group'of'_sre.SRE_Match'objects}

            820.0410.0000.0410.000{method'readlines'of'file'objects}

            820.0160.0000.0160.000{open}

            10.0040.0042.9502.950CLineCounter.py:154(CountDir)

            由tottime可見,此處的性能瓶頸在于CalcLines()函數(shù)和其中的正則表達(dá)式處理。而isspace()和strip()方法及l(fā)en()函數(shù)因調(diào)用次數(shù)較多,總的耗時(shí)也頗為可觀。

            作為對比,以下給出一種未使用正則表達(dá)式的統(tǒng)計(jì)實(shí)現(xiàn):

            defCalcLines(line,isBlockComment):

            lineType,lineLen=0,len(line)

            line=line+'\n'#添加一個(gè)字符防止iChar+1時(shí)越界

            iChar,isLineComment=0,False

            whileiChar

            #行結(jié)束符(Windows:\r\n;Mac:\r;Unix:\n)

            ifline[iChar]=='\r'orline[iChar]=='\n':

            break

            elifline[iChar]==''orline[iChar]=='\t':#空白字符

            iChar+=1;continue

            elifline[iChar]=='/'andline[iChar+1]=='/':#行注釋

            isLineComment=True

            lineType|=2;iChar+=1#跳過'/'

            elifline[iChar]=='/'andline[iChar+1]=='*':#塊注釋開始符

            isBlockComment[0]=True

            lineType|=2;iChar+=1

            elifline[iChar]=='*'andline[iChar+1]=='/':#塊注釋結(jié)束符

            isBlockComment[0]=False

            lineType|=2;iChar+=1

            else:

            ifisLineCommentorisBlockComment[0]:

            lineType|=2

            else:

            lineType|=1

            iChar+=1

            returnlineType#Bitmap:0空行,1代碼,2注釋,3代碼和注釋

            在CalcLines()函數(shù)中。參數(shù)line為當(dāng)前文件行字符串,參數(shù)isBlockComment指示當(dāng)前行是否位于塊注釋內(nèi)。該函數(shù)直接分析句法,而非模式匹配。注意,行結(jié)束符可能因操作系統(tǒng)而異,因此應(yīng)區(qū)分CR(回車)和LF(換行)符。此外,也可在讀取文件時(shí)采用"rU"(即通用換行模式),該模式會(huì)將行結(jié)束符\r\n和\r替換為\n。

            基于新的CalcLines()函數(shù),CountFileLines()函數(shù)需作如下修改:

            defCountFileLines(filePath,isRawReport=True,isShortName=False):

            fileExt=os.path.splitext(filePath)

            iffileExt[1]!='.c'andfileExt[1]!='.h':

            return

            isBlockComment=[False]#或定義為全局變量,以保存上次值

            lineCountInfo=[0]*4#[代碼總行數(shù),代碼行數(shù),注釋行數(shù),空白行數(shù)]

            withopen(filePath,'r')asfile:

            forlineinfile:

            lineType=CalcLines(line,isBlockComment)

            lineCountInfo[0]+=1

            iflineType==0:lineCountInfo[3]+=1

            eliflineType==1:lineCountInfo[1]+=1

            eliflineType==2:lineCountInfo[2]+=1

            eliflineType==3:lineCountInfo[1]+=1;lineCountInfo[2]+=1

            else:

            assertFalse,'UnexpectedlineType:%d(0~3)!'%lineType

            ifisRawReport:

            globalrawCountInfo

            rawCountInfo[:-1]=[x+yforx,yinzip(rawCountInfo[:-1],lineCountInfo)]

            rawCountInfo[-1]+=1

            elifisShortName:

            detailCountInfo.append([os.path.basename(filePath),lineCountInfo])

            else:

            detailCountInfo.append([filePath,lineCountInfo])

            將這種統(tǒng)計(jì)實(shí)現(xiàn)命名為BCLineCounter.py。通過cProfile命令分析其性能,截取out.txt文件部分內(nèi)容如下:

            250316245433620.25xtm_mgr.c

            1408729373632106169380.26

            286013functioncalls(285979primitivecalls)in3.926seconds

            Orderedby:internaltime

            ncallstottimepercallcumtimepercallfilename:lineno(function)

            1408723.3340.0003.4750.000BCLineCounter.py:15(CalcLines)

            830.4090.0053.9030.047BCLineCounter.py:45(CountFileLines)

            141593/1415850.1420.0000.1420.000{len}

            820.0140.0000.0140.000{open}

            10.0040.0040.0040.004collections.py:1()

            4160.0030.0000.0040.000ntpath.py:96(splitdrive)

            840.0020.0000.0020.000{nt._isdir}

            10.0020.0020.0070.007argparse.py:62()

            10.0020.0023.9263.926BCLineCounter.py:6()

            可見,性能并不如CLineCounter.py。因此,使用標(biāo)準(zhǔn)庫(如re)提供的函數(shù)或方法,不失為明智的選擇。

            此外,對比BCLineCounter.py和CLineCounter.py的詳細(xì)行數(shù)報(bào)告可知,兩者的統(tǒng)計(jì)結(jié)果存在細(xì)微差異(正負(fù)誤差不超過5行)。差異主要體現(xiàn)在有效代碼行和純注釋行統(tǒng)計(jì)上,因?yàn)榭傂袛?shù)和空白行數(shù)通常不會(huì)出現(xiàn)統(tǒng)計(jì)誤差。那么,哪種實(shí)現(xiàn)更可靠呢?

            作者首先想到挑選存在統(tǒng)計(jì)差異的文件,人工或半人工地刪除純注釋行和空白行,從而得到精確的有效代碼行數(shù)。之所以不編寫腳本自動(dòng)刪除上述類型的文件行,是因?yàn)樽髡邔τ谧⑨屝械慕馕鲆呀?jīng)存在誤差,無法作為基準(zhǔn)參考。

            C語言預(yù)處理器可剔除代碼注釋,但同時(shí)也會(huì)剔除#if0...#endif之類的無效語句,不滿足要求。于是,作者用UEStudio打開源文件,進(jìn)入【搜索(Search)】|【替換(Replace)】頁,選擇Unix正則表達(dá)式引擎,用^\s*/\*.*\*/匹配單行注釋(/*abc*/)并替換為空字符,用^\s*//.*$匹配單行注釋(//abc)并替換為空字符。然后,查找并手工刪除跨行注釋及其他未匹配到的單行注釋。最后,選擇UltraEdit正則表達(dá)式引擎,用%[^t]++^p匹配空行并替換為空字符,即可刪除所有空行。注意,UEStudio幫助中提供的正則表達(dá)式^p$一次只能刪除一個(gè)空行。

            按上述方式處理兩個(gè)大型文件后,初步發(fā)現(xiàn)BCLineCounter.py關(guān)于有效代碼行數(shù)的統(tǒng)計(jì)是正確的。然而,這種半人工處理方式太過低效,因此作者想到讓兩個(gè)腳本處理相同的文件,并輸出有效代碼行或純注釋行的內(nèi)容,將其通過AraxisMerge對比。該工具會(huì)高亮差異行,且人工檢查很容易鑒別正誤。此處,作者假定對于給定文件的給定類型行數(shù),BCLineCounter.py和CLineCounter.py必有一者統(tǒng)計(jì)正確(可作基準(zhǔn))。當(dāng)然,也有可能兩者均有誤差。因此,若求保險(xiǎn),也可同時(shí)輸出類型和行內(nèi)容,再行對比。

            綜合檢查結(jié)果發(fā)現(xiàn),BCLineCounter.py較CLineCounter.py更為健壯。這是因?yàn)?,模式匹配需要處理的場景繁多,極易疏漏。例如,CLineCounter.py無法正確處理下面的代碼片段:

            voidtest(){

            /*/multiline,

            comment*/

            inta=1/2;//comment

            //*Assignavalue

            }

            讀者若有興趣,可修改和調(diào)試CLineCounter.py里的正則表達(dá)式,使該腳本高效而健壯。

            以上內(nèi)容為大家介紹了Python性能分析,希望對大家有所幫助,如果想要了解更多Python相關(guān)知識,請關(guān)注IT培訓(xùn)機(jī)構(gòu):千鋒教育。

            聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
            10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
            請您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
            免費(fèi)領(lǐng)取
            今日已有369人領(lǐng)取成功
            劉同學(xué) 138****2860 剛剛成功領(lǐng)取
            王同學(xué) 131****2015 剛剛成功領(lǐng)取
            張同學(xué) 133****4652 剛剛成功領(lǐng)取
            李同學(xué) 135****8607 剛剛成功領(lǐng)取
            楊同學(xué) 132****5667 剛剛成功領(lǐng)取
            岳同學(xué) 134****6652 剛剛成功領(lǐng)取
            梁同學(xué) 157****2950 剛剛成功領(lǐng)取
            劉同學(xué) 189****1015 剛剛成功領(lǐng)取
            張同學(xué) 155****4678 剛剛成功領(lǐng)取
            鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
            董同學(xué) 138****2867 剛剛成功領(lǐng)取
            周同學(xué) 136****3602 剛剛成功領(lǐng)取
            相關(guān)推薦HOT
            Python重命名和刪除文件

            python的os模塊提供了幫你執(zhí)行文件處理操作的方法,比如重命名和刪除文件。要使用這個(gè)模塊,你必須先導(dǎo)入它,然后才可以調(diào)用相關(guān)的各種功能。re...詳情>>

            2023-11-07 20:49:35
            python 序列化及其相關(guān)模塊

            什么是序列化對象?我們把對象(變量)從內(nèi)存中編程可存儲(chǔ)或傳輸?shù)倪^程稱之為序列化,在python中稱為pickle,其他語言稱之為serialization,marshal...詳情>>

            2023-11-07 20:42:23
            python生成器函數(shù)

            為什么叫生成器函數(shù)?因?yàn)樗S著時(shí)間的推移生成了一個(gè)數(shù)值隊(duì)列。一般的函數(shù)在執(zhí)行完畢之后會(huì)返回一個(gè)值然后退出,但是生成器函數(shù)會(huì)自動(dòng)掛起,然...詳情>>

            2023-11-07 20:31:35
            python 字典操作方法詳解

            字典是一種通過名字或者關(guān)鍵字引用的得數(shù)據(jù)結(jié)構(gòu),key類型需要時(shí)被哈希,其鍵可以是數(shù)字、字符串、元組,這種結(jié)構(gòu)類型也稱之為映射。字典類型是P...詳情>>

            2023-11-07 20:09:59
            python 集合操作方法詳解

            集合set集合用于包含一組無序的對象。與列表和元組不同,集合是無序的,也無法通過數(shù)字進(jìn)行索引。此外,集合中的元素不能重復(fù)。set和dict一樣,...詳情>>

            2023-11-07 20:06:23