Python 性能優化

2021-02-21 Python開發者

(點擊上方藍字,快速關注我們)

來源:xybaby

www.cnblogs.com/xybaby/p/6510941.html

如有好文章投稿,請點擊 → 這裡了解詳情

正文

注意:本文除非特殊指明,」python「都是代表CPython,即C語言實現的標準python,且本文所討論的是版本為2.7的CPython。

python為什麼性能差:

當我們提到一門程式語言的效率時:通常有兩層意思,第一是開發效率,這是對程式設計師而言,完成編碼所需要的時間;另一個是運行效率,這是對計算機而言,完成計算任務所需要的時間。編碼效率和運行效率往往是魚與熊掌的關係,是很難同時兼顧的。不同的語言會有不同的側重,python語言毫無疑問更在乎編碼效率,life is short,we use python。

雖然使用python的編程人員都應該接受其運行效率低的事實,但python在越多越來的領域都有廣泛應用,比如科學計算 、web伺服器等。程式設計師當然也希望python能夠運算得更快,希望python可以更強大。

首先,python相比其他語言具體有多慢,這個不同場景和測試用例,結果肯定是不一樣的。這個網址給出了不同語言在各種case下的性能對比,這一頁是python3和C++的對比,下面是兩個case:

python運算效率低,具體是什麼原因呢,下列羅列一些

第一:python是動態語言

一個變量所指向對象的類型在運行時才確定,編譯器做不了任何預測,也就無從優化。舉一個簡單的例子: r = a + b。 a和b相加,但a和b的類型在運行時才知道,對於加法操作,不同的類型有不同的處理,所以每次運行的時候都會去判斷a和b的類型,然後執行對應的操作。而在靜態語言如C++中,編譯的時候就確定了運行時的代碼。

另外一個例子是屬性查找,關於具體的查找順序在《python屬性查找》中有詳細介紹。簡而言之,訪問對象的某個屬性是一個非常複雜的過程,而且通過同一個變量訪問到的python對象還都可能不一樣(參見Lazy property的例子)。而在C語言中,訪問屬性用對象的地址加上屬性的偏移就可以了。

第二:python是解釋執行,但是不支持JIT(just in time compiler)。雖然大名鼎鼎的google曾經嘗試Unladen Swallow 這個項目,但最終也折了。

第三:python中一切都是對象,每個對象都需要維護引用計數,增加了額外的工作。

第四:python GIL

GIL是Python最為詬病的一點,因為GIL,python中的多線程並不能真正的並發。如果是在IO bound的業務場景,這個問題並不大,但是在CPU BOUND的場景,這就很致命了。所以筆者在工作中使用python多線程的情況並不多,一般都是使用多進程(pre fork),或者在加上協程。即使在單線程,GIL也會帶來很大的性能影響,因為python每執行100個opcode(默認,可以通過sys.setcheckinterval()設置)就會嘗試線程的切換,具體的原始碼在ceval.c::PyEval_EvalFrameEx。

第五:垃圾回收,這個可能是所有具有垃圾回收的程式語言的通病。python採用標記和分代的垃圾回收策略,每次垃圾回收的時候都會中斷正在執行的程序,造成所謂的頓卡。infoq上有一篇文章,提到禁用Python的GC機制後,Instagram性能提升了10%。感興趣的讀者可以去細讀。

Be pythonic

我們都知道 過早的優化是罪惡之源,一切優化都需要基於profile。但是,作為一個python開發者應該要pythonic,而且pythonic的代碼往往比non-pythonic的代碼效率高一些,比如:

dict的iteritems 而不是items(同itervalues,iterkeys)

使用generator,特別是在循環中可能提前break的情況

基於profile的優化

即使我們的代碼已經非常pythonic了,但可能運行效率還是不能滿足預期。我們也知道80/20定律,絕大多數的時間都耗費在少量的代碼片段裡面了,優化的關鍵在於找出這些瓶頸代碼。方式很多:到處加log列印時間戳、或者將懷疑的函數使用timeit進行單獨測試,但最有效的是使用profile工具。

python profilers

對於python程序,比較出名的profile工具有三個:profile、cprofile和hotshot。其中profile是純python語言實現的,Cprofile將profile的部分實現native化,hotshot也是C語言實現,hotshot與Cprofile的區別在於:hotshot對目標代碼的運行影響較小,代價是更多的後處理時間,而且hotshot已經停止維護了。需要注意的是,profile(Cprofile hotshot)只適合單線程的python程序。

對於多線程,可以使用yappi,yappi不僅支持多線程,還可以精確到CPU時間

對於協程(greenlet),可以使用greenletprofiler,基於yappi修改,用greenlet context hook住thread context

下面給出一段編造的」效率低下「的代碼,並使用Cprofile來說明profile的具體方法以及我們可能遇到的性能瓶頸。

# -*- coding: UTF-8 -*-

 

from cProfile import Profile

import math

def foo():

    return foo1()

 

def foo1():

    return foo2()

 

def foo2():

    return foo3()

 

def foo3():

    return foo4()

 

def foo4():

    return "this call tree seems ugly, but it always happen"

 

def bar():

    ret = 0

    for i in xrange(10000):

        ret += i * i + math.sqrt(i)

    return ret

 

def main():

    for i in range(100000):

        if i % 10000 == 0:

            bar()

        else:

            foo()

 

if __name__ == '__main__':

    prof = Profile()

    prof.runcall(main)

    prof.print_stats()

    #prof.dump_stats('test.prof') # dump profile result to test.prof

 

code for profile

運行結果如下:

對於上面的的輸出,每一個欄位意義如下:

ncalls 函數總的調用次數

tottime 函數內部(不包括子函數)的佔用時間

percall(第一個) tottime/ncalls

cumtime 函數包括子函數所佔用的時間

percall(第二個)cumtime/ncalls

filename:lineno(function) 文件:行號(函數)

代碼中的輸出非常簡單,事實上可以利用pstat,讓profile結果的輸出多樣化,具體可以參見官方文檔python profiler。

profile GUI tools

雖然Cprofile的輸出已經比較直觀,但我們還是傾向於保存profile的結果,然後用圖形化的工具來從不同的維度來分析,或者比較優化前後的代碼。查看profile結果的工具也比較多,比如,visualpytune、qcachegrind、runsnakerun,本文用visualpytune做分析。對於上面的代碼,按照注釋生成修改後重新運行生成test.prof文件,用visualpytune直接打開就可以了,如下:

欄位的意義與文本輸出基本一致,不過便捷性可以點擊欄位名排序。左下方列出了當前函數的calller(調用者),右下方是當前函數內部與子函數的時間佔用情況。上如是按照cumtime(即該函數內部及其子函數所佔的時間和)排序的結果。

造成性能瓶頸的原因通常是高頻調用的函數、單次消耗非常高的函數、或者二者的結合。在我們前面的例子中,foo就屬於高頻調用的情況,bar屬於單次消耗非常高的情況,這都是我們需要優化的重點。

python-profiling-tools中介紹了qcachegrind和runsnakerun的使用方法,這兩個colorful的工具比visualpytune強大得多。具體的使用方法請參考原文,下圖給出test.prof用qcachegrind打開的結果。

qcachegrind確實要比visualpytune強大。從上圖可以看到,大致分為三部:。第一部分同visualpytune類似,是每個函數佔用的時間,其中Incl等同於cumtime, Self等同於tottime。第二部分和第三部分都有很多標籤,不同的標籤標示從不同的角度來看結果,如圖上所以,第三部分的「call graph」展示了該函數的call tree並包含每個子函數的時間百分比,一目了然。

profile針對優化

知道了熱點,就可以進行針對性的優化,而這個優化往往根具體的業務密切相關,沒用萬能鑰匙,具體問題,具體分析。個人經驗而言,最有效的優化是找產品經理討論需求,可能換一種方式也能滿足需求,少者稍微折衷一下產品經理也能接受。次之是修改代碼的實現,比如之前使用了一個比較通俗易懂但效率較低的算法,如果這個算法成為了性能瓶頸,那就考慮換一種效率更高但是可能難理解的算法、或者使用dirty Flag模式。對於這些同樣的方法,需要結合具體的案例,本文不做贅述。

接下來結合python語言特性,介紹一些讓python代碼不那麼pythonic,但可以提升性能的一些做法

第一:減少函數的調用層次

每一層函數調用都會帶來不小的開銷,特別對於調用頻率高,但單次消耗較小的calltree,多層的函數調用開銷就很大,這個時候可以考慮將其展開。

對於之前調到的profile的代碼,foo這個call tree非常簡單,但頻率高。修改代碼,增加一個plain_foo()函數, 直接返回最終結果,關鍵輸出如下:

跟之前的結果對比:

可以看到,優化了差不多3倍。

第二:優化屬性查找

上面提到,python 的屬性查找效率很低,如果在一段代碼中頻繁訪問一個屬性(比如for循環),那麼可以考慮用局部變量代替對象的屬性。

第三:關閉GC

在本文的第一章節已經提到,關閉GC可以提升python的性能,GC帶來的頓卡在實時性要求比較高的應用場景也是難以接受的。但關閉GC並不是一件容易的事情。我們知道python的引用計數只能應付沒有循環引用的情況,有了循環引用就需要靠GC來處理。在python語言中, 寫出循環引用非常容易。比如:

case 1:

  a, b = SomeClass(), SomeClass()

  a.b, b.a = b, a

   

case 2:

  lst = []

  lst.append(lst)

case 3:

  self.handler = self.some_func

當然,大家可能說,誰會這麼傻,寫出這樣的代碼,是的,上面的代碼太明顯,當中間多幾個層級之後,就會出現「間接」的循環應用。在python的標準庫 collections裡面的OrderedDict就是case2:

要解決循環引用,第一個辦法是使用弱引用(weakref),第二個是手動解循環引用。

第四:setcheckinterval

如果程序確定是單線程,那麼修改checkinterval為一個更大的值,這裡有介紹。

第五:使用__slots__

slots最主要的目的是用來節省內存,但是也能一定程度上提高性能。我們知道定義了__slots__的類,對某一個實例都會預留足夠的空間,也就不會再自動創建__dict__。當然,使用__slots__也有許多注意事項,最重要的一點,繼承鏈上的所有類都必須定義__slots__,python doc有詳細的描述。下面看一個簡單的測試例子:

class BaseSlots(object):

    __slots__ = ['e', 'f', 'g']

 

class Slots(BaseSlots):

    __slots__ = ['a', 'b', 'c', 'd']

    def __init__(self):

        self.a = self.b = self.c = self.d = self.e = self.f  = self.g = 0

 

class BaseNoSlots(object):

        pass

 

class NoSlots(BaseNoSlots):

    def __init__(self):

        super(NoSlots,self).__init__()

        self.a = self.b = self.c = self.d = self.e = self.f  = self.g = 0

 

def log_time(s):

    begin = time.time()

    for i in xrange(10000000):

        s.a,s.b,s.c,s.d, s.e, s.f, s.g

    return time.time() - begin

 

if __name__ == '__main__':

    print 'Slots cost', log_time(Slots())

    print 'NoSlots cost', log_time(NoSlots())

輸出結果:

Slots cost 3.12999987602

NoSlots cost 3.48100018501

python C擴展

也許通過profile,我們已經找到了性能熱點,但這個熱點就是要運行大量的計算,而且沒法cache,沒法省略。。。這個時候就該python的C擴展出馬了,C擴展就是把部分python代碼用C或者C++重新實現,然後編譯成動態連結庫,提供接口給其它python代碼調用。由於C語言的效率遠遠高於python代碼,所以使用C擴展是非常普遍的做法,比如我們前面提到的cProfile就是基於_lsprof.so的一層封裝。python的大所屬對性能有要求的庫都使用或者提供了C擴展,如gevent、protobuff、bson。

筆者曾經測試過純python版本的bson和cbson的效率,在綜合的情況下,cbson快了差不多10倍!

python的C擴展也是一個非常複雜的問題,本文僅給出一些注意事項:

第一:注意引用計數的正確管理

這是最難最複雜的一點。我們都知道python基於指針技術來管理對象的生命周期,如果在擴展中引用計數出了問題,那麼要麼是程序崩潰,要麼是內存洩漏。更要命的是,引用計數導致的問題很難debug。。。

C擴展中關於引用計數最關鍵的三個詞是:steal reference,borrowed reference,new reference。建議編寫擴展代碼之前細讀python的官方文檔。

第二:C擴展與多線程

這裡的多線程是指在擴展中new出來的C語言線程,而不是python的多線程,出了python doc裡面的介紹,也可以看看《python cookbook》的相關章節。

第三:C擴展應用場景

僅適合與業務代碼的關係不那麼緊密的邏輯,如果一段代碼大量業務相關的對象 屬性的話,是很難C擴展的

將C擴展封裝成python代碼可調用的接口的過程稱之為binding,Cpython本身就提供了一套原生的API,雖然使用最為廣泛,但該規範比較複雜。很多第三方庫做了不同程度的封裝,以便開發者使用,比如boost.python、cython、ctypes、cffi(同時支持pypy cpython),具體怎麼使用可以google。

beyond CPython

儘管python的性能差強人意,但是其易學易用的特性還是贏得越來越多的使用者,業界大牛也從來沒有放棄對python的優化。這裡的優化是對python語言設計上、或者實現上的一些反思或者增強。這些優化項目一些已經夭折,一些還在進一步改善中,在這個章節介紹目前還不錯的一些項目。

cython

前面提到cython可以用到binding c擴展,但是其作用遠遠不止這一點。

Cython的主要目的是加速python的運行效率,但是又不像上一章節提到的C擴展那麼複雜。在Cython中,寫C擴展和寫python代碼的複雜度差不多(多虧了Pyrex)。Cython是python語言的超集,增加了對C語言函數調用和類型聲明的支持。從這個角度來看,cython將動態的python代碼轉換成靜態編譯的C代碼,這也是cython高效的原因。使用cython同C擴展一樣,需要編譯成動態連結庫,在linux環境下既可以用命令行,也可以用distutils。

如果想要系統學習cython,建議從cython document入手,文檔寫得很好。下面通過一個簡單的示例來展示cython的使用方法和性能(linux環境)。

首先,安裝cython:

pip install Cython

下面是測試用的python代碼,可以看到這兩個case都是運算複雜度比較高的例子:

def f():

    return x**2-x

 

def integrate_f(a, b, N):

    s = 0

    dx = (b-a)/N

    for i in range(N):

        s += f(a+i*dx)

    return s * dx

 

def main():

    import time

    begin = time.time()

    for i in xrange(10000):

        for i in xrange(100):f(10)

    print 'call f cost:', time.time() - begin

    begin = time.time()

    for i in xrange(10000):

        integrate_f(1.0, 100.0, 1000)

    print 'call integrate_f cost:', time.time() - begin

 

if __name__ == '__main__':

    main()

運行結果:

call f cost: 0.215116024017

call integrate_f cost: 4.33698010445

不改動任何python代碼也可以享受到cython帶來的性能提升,具體做法如下:

from distutils.core import setup

from Cython.Build import cythonize

 

setup(

  name = 'cython_example',

  ext_modules = cythonize("cython_example.pyx"),

)

可以看到 增加了兩個文件,對應中間結果和最後的動態連結庫

運行結果:

call f cost: 0.0874309539795

call integrate_f cost: 2.92381191254

性能提升了大概兩倍,我們再來試試cython提供的靜態類型(static typing),修改cython_example.pyx的核心代碼,替換f()和integrate_f()的實現如下:

def f(double x): # 參數靜態類型

    return x**2-x

 

def integrate_f(double a, double b, int N):

    cdef int i

    cdef double s, dx

    s = 0

    dx = (b-a)/N

    for i in range(N):

        s += f(a+i*dx)

    return s * dx

然後重新運行上面的第三 四步:結果如下

call f cost: 0.042387008667

call integrate_f cost: 0.958620071411

上面的代碼,只是對參數引入了靜態類型判斷,下面對返回值也引入靜態類型判斷。

替換f()和integrate_f()的實現如下:

cdef double f(double x): # 返回值也有類型判斷

    return x**2-x

 

cdef double integrate_f(double a, double b, int N):

    cdef int i

    cdef double s, dx

    s = 0

    dx = (b-a)/N

    for i in range(N):

        s += f(a+i*dx)

    return s * dx

然後重新運行上面的第三 四步:結果如下

call f cost: 1.19209289551e-06

call integrate_f cost: 0.187038183212

Amazing!

pypy

pypy是CPython的一個替代實現,其最主要的優勢就是pypy的速度,下面是官網的測試結果:

在實際項目中測試,pypy大概比cpython要快3到5倍!pypy的性能提升來自JIT Compiler。在前文提到google的Unladen Swallow 項目也是想在CPython中引入JIT,在這個項目失敗後,很多開發人員都開始加入pypy的開發和優化。另外pypy佔用的內存更少,而且支持stackless,基本等同於協程。

pypy的缺點在於對C擴展方面支持的不太好,需要使用CFFi來做binding。對於使用廣泛的library來說,一般都會支持pypy,但是小眾的、或者自行開發的C擴展就需要重新封裝了。

ChangeLog

2017.03.10 增加了對__slots__的介紹

references

程式語言benchmark

python屬性查找

python profiler

yappi

greenletprofiler

python-profiling-tools

python C API

cython

Pyrex

cython document

pypy

看完本文有收穫?請轉發分享給更多人

關注「Python開發者」,提升Python技能

相關焦點

  • Python 性能優化的20條招數
    如果想要在 python 中使用已經有C類庫,使用 ctypes 是很好的選擇,有一些基準測試下,python2+ctypes 是性能最好的方式。Cython: Cython 是 CPython 的超集,用於簡化編寫C擴展的過程。Cython 的優點是語法簡潔,可以很好地兼容 numpy 等包含大量C擴展的庫。
  • Python性能優化的20條招數
    如果想要在 python 中使用已經有C類庫,使用 ctypes 是很好的選擇,有一些基準測試下,python2+ctypes 是性能***的方式。Cython: Cython 是 CPython 的超集,用於簡化編寫C擴展的過程。Cython 的優點是語法簡潔,可以很好地兼容 numpy 等包含大量C擴展的庫。Cython 的使得場景一般是針對項目中某個算法或過程的優化。
  • 介紹幾款Python性能優化工具
    所以在程序運行過程中,如果發現運行時間太長或者內存佔用過大,就需要對程序的執行過程進行一些監測,找到有問題的地方,進行優化。今天我們就來分享一些平時能用上的Python性能分析工具。memory_profilermemory_profiler是監控python進程的神器,只需要在函數加一個裝飾器就可以輸出每行代碼的內存使用情況安裝:pip install memory_profiler使用:import
  • 利用python解決凸優化問題
    凸優化問題下面我們給出凸優化問題的定義:其中函數f和g是凸函數,h為仿射函數(affine functions),仿射函數可以理解為簡單的線性變換這一點很重要,如果優化的函數沒有這種性質,我們對其優化一般採用現代優化算法,比如遺傳算法、粒子群算法、混沌算法等等。基於python語言的凸優化問題求解用過matlab的讀者可能聽過matlab中cvx工具包,這是解決凸函數的工具包。
  • 案例詳解:優化Python編程的4個妙招
    此時就該揮動優化代碼的仙女棒了。代碼最優化,簡單來講,就是在保證結果正確的前提下儘可能減少執行任務的運算量。來算算for循環完成任務所需的運算量吧:首先計算出上面數組中指數1和3代表的城市間的距離。如果想減少計算量,同時又想得到正確的結果,應該採取什麼優化方法呢?這裡,使用前綴數組來計算距離是一種可能的優化方案。它是這樣運算的:大家能理解這裡的做法嗎?這樣只需一次計算就得到了同樣的城市距離!這一方法最棒的地方就是,不管指數間的差距是1還是100000,只需一次計算就能算出任意兩個指數間的距離。是不是很神奇?
  • Android性能優化典範
    摘要:Google在Udacity上的《Android性能優化》在線課程詳細介紹了該如何優化性能,這些課程是Google之前在Youtube上發布的Android性能優化典範專題課程的細化與補充。本文是對渲染、運算、內存、電量四個篇章的學習筆記。
  • Python 為了提升性能,竟運用了共享經濟
    現在各行各業可是都掀起了一股python學習的熱潮,幾乎每位職場人士都在學習和使用python。python大家都很熟悉了,共享經濟大家也都知道,可是python運用了共享經濟這件事你了解嗎?想知道的話,就來看小編今天跟大家分享的這篇「Python 為了提升性能,竟運用了共享經濟」的文章吧。
  • Python遇到性能瓶頸怎麼辦?
    在Python遇到性能瓶頸時怎麼辦?
  • Python 調用 C 模塊以及性能分析
    (點擊上方藍字,快速關注我們)來源:Xjngwww.cnblogs.com/Xjng/p/5120853.html如有好文章投稿,請點擊 → 這裡了解詳情一.c,ctypes和python/hello_world.so')c_lib.hello_world()二.測試c的性能和python的差別sum.cint sum(int num){    long sum=0;    int i =0;    for( i=1;i<=num;i++){        sum=sum
  • Python 性能分析入門指南
    $ time python yourprogram.pyreal    0m1.028suser    0m0.001ssys     0m0.003s三個輸出測量值之間的詳細意義在這裡 stackoverflow article,但簡介在這:你會有你的應用程式用完了多少 CPU 周期的即視感,不管系統上其他運行的程序添加的系統和用戶時間
  • Greenplum內核優化實戰:手把手教你提升數倍SELECT性能
    6 OLTP (TPC-B) 性能提升60倍),已經可以滿足大部分OLTP應用場景。這個過程非一日之功,也涉及到系統的各個層面的優化和重構,本文手把手的示範如何分析發現瓶頸,以及如何優化內核提升性能,揭秘MPP資料庫內核調優,鼓勵歡迎更多人在社區裡參與這類工作。本文的例子採用分支6.0.0-beta.1。測試環境是GCP的機器,32 vCPUs, 28.8 GB, 512 SSD persistent disk。作業系統是Ubuntu 18.04.2 LTS。
  • python性能提高10倍的通用方法
    這種工具可用來存儲和處理大型矩陣,比Python自身的嵌套列表要高效的多,支持大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫,在整個python生態中佔有舉足輕重的作用,本篇文章旨在講解如何藉助它來提升python的計算性能。
  • 性能優化之PHP優化
    在我們平常寫代碼的過程中,除了資料庫的優化,針對與文件的優化,我們還需要對PHP執行優化,當然對於老司機來說,這都是毛毛雨咯~但是畢竟有新手嘛,於是,我整理這麼一片文章。(未完待續...)性能優化之PHP優化(一):PHP結構1.字符串
  • 系統架構性能優化思路
    來源:https://4m.cn/rN8IB今天談下業務系統性能問題分析診斷和性能優化方面的內容。這篇文章重點還是談已經上線的業務系統後續出現性能問題後的問題診斷和優化重點。資料庫性能調優拿Oracle資料庫來說,影響資料庫性能的因素包括:系統、資料庫、網絡。資料庫的優化包括:優化資料庫磁碟I/O、優化回滾段、優化Rrdo日誌、優化系統全局區、優化資料庫對象。
  • Android性能優化總結
    這是來自一位粉絲「MeloDev」的投稿,講真,我這裡投稿的不少,但是只有我自己覺得很不錯的才會通過,這篇文章我覺得對大家有用,而且性能優化也算是我面試必問的一個話題了,所以這裡推薦給大家。程序執行效率:糟糕的代碼會嚴重影響程序的運行效率,UI線程過多的任務會阻塞應用的正常運行,長時間持有某個對象會導致潛在的內存洩露,頻繁的IO操作、網絡操作而不用緩存會嚴重影響程序的運行效率。一、布局複雜度的優化關於布局的優化,主要分兩個大方向1.
  • 酷睿i5性能這樣瞬間提升20倍!
    安裝:% bash Anaconda2-4.3.0-Linux-x86_64.sh安裝英特爾加速器,作為一個單獨的、可開啟關閉的「環境」%conda config --add channels intel % conda create --name intelpy intelpython2_full python=2運行示例程序,看到在我的openSUSE
  • python+C、C++混合編程的應用
    有的語言專注於簡單高效,比如python,內建的list,dict結構比c/c++易用太多,但同樣為了安全、易用,語言也犧牲了部分性能。在有些領域,比如通信,性能很關鍵,但並不意味這個領域的coder只能苦苦掙扎於c/c++的陷阱中,比如可以使用多種語言混合編程。
  • Python性能分析技巧
    1.分析一行代碼要檢查一行python代碼的執行時間,請使用**%timeit**。3.代碼塊中的每一行代碼進行時間分析到目前為止,我們只在分析一行代碼或代碼塊時查看摘要統計信息,如果我們想評估代碼塊中每一行代碼的性能呢?使用Line_profiler 。Line_profiler 包可用於對任何函數執行逐行分析。
  • etcd 的性能怎麼樣?需要優化嗎?
    可以將 etcd 集群劃分成幾個核心的部分:例如藍色的 Raft 層、紅色的 Storage 層,Storage 層內部又分為 treeIndex 層和 boltdb 底層持久化存儲 key/value 層。它們的每一層都有可能造成 etcd 的性能損失。首先來看 Raft 層,Raft 需要通過網絡同步數據,網絡 IO 節點之間的 RTT 和 / 帶寬會影響 etcd 的性能。
  • 讓Python代碼更快運行的 5 種方法
    如果你想讓Python在同一硬體上運行得更快,你有兩個基本選擇,而每個都會有一個缺點:·您可以創建一個默認運行時所使用的替代語言(CPython的實現)——一個主要的任務,但它最終只會是CPython的一個簡易替代者。·您也可以利用某些速度優化器重寫現有Python代碼,這意味著程式設計師要花更多精力編寫代碼,但不需要在運行時加以改變。