python高手之路 筆記4 性能與優(yōu)化專題

性能與優(yōu)化


數(shù)據(jù)結(jié)構(gòu)

多利用python本身的代碼

  • dict.get()示例
#dict.get(key, default=None)
#key -- 這是要搜索在字典中的鍵粟焊。
#default -- 這是要返回鍵不存在的的情況下默認(rèn)值鳍烁。
def get_fruits(basket, fruit):
    return basket.get(fruit, set())
  • set()示例
#集合做差集,判斷是否有指定元素之外的元素
def has_invalid_fields(fields):
    return bool(set(fields) - set(['foo', 'bar'])
  • defaultdict()示例
import collections
def add_animal_in_family(species, animal, family):
    species[family].add(animal)
species = collections.defaultdict(set)
add_animal_in_family(species, 'cat', 'felidea')

每次試圖從字典中訪問一個不存在的元素个曙,defaultdict都會使用作為參數(shù)傳入的這個函數(shù)去構(gòu)造一個新值而不是拋出KeyError察郁。

性能分析

  • 使用cProfile模塊
$ python -m cProfile myscript.py

可以使用-s選項按其他字段進(jìn)行排序伙菜,如-s time

  • C語言分析Valgrind以及可視化工具KCacheGrind

$ python -m cProfile -o myscript.cprof myscript.py
$ pyprof2calltree -k -i myscript.cprof

- dis模塊:python字節(jié)碼的反編譯器

#### namedtuple和slots
- python中擁有一些固定屬性的簡單對象會存儲所有的屬性在一個字典內(nèi)轩缤,這個字典本身被存在`__dict__`屬性中:
```python
class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
p = Point(1, 2)
p.__dict__
p.z = 42
  • 可以通過__slots__聲明來減少內(nèi)存開銷
class Foobar(object):
    __slots__ = 'x'
    def __init__(self, x):
        self.x = x
  • 使用python包 memory_profiler檢測內(nèi)存使用情況
$ python -m memory_profiler object.py

緩存加速技術(shù)

  • memoization是指通過緩存函數(shù)返回結(jié)果來加速函數(shù)調(diào)用的一種技術(shù)。僅當(dāng)函數(shù)是純函數(shù)時結(jié)果才可以被緩存贩绕,也就是說函數(shù)不能有任何副作用或輸出火的,也不能依賴任何全局狀態(tài)。
  • 基本的memoization技術(shù)
import math
_SIN_MEMOIZED_VALUES = {}
def memoized_sin(x):
    if x not in _SIN_MEMOIZED_VALUES:
        _SIN_MEMOIZED_VALUES[x] = math.sin(x)
    return _SIN_MEMOIZED_VALUES[x]
  • 使用functools.lru_cache實現(xiàn)
import functools
import math
@functools.lru_cache(maxsize = 2)
def memoized_sin(x):
    return math.sin(x)

使用后可以使用memoized_sin.cache_info()查看緩存情況

GIL(Global Interpreter Lock, 全局解釋器鎖)

利用memoryview實現(xiàn)淺拷貝(引用)

  • 使用memoryview可以在內(nèi)存區(qū)域的任何點放入數(shù)據(jù)
ba = bytearray(8)
ba_at_4 = memoryview(ba)[4:]
#引用bytearray淑倾,從其偏移索引4到其結(jié)尾
with open("/dev/urandom", "rb") as source:
    source.readinto(ba_at_4)
    #將/dev/urandom的內(nèi)容寫入bytearray中從偏移索引4到結(jié)尾的位置馏鹤,精確且高效地只讀寫了4字節(jié)

多進(jìn)程與多線程

  • multiprocessing模塊不僅可以有效地將負(fù)載分散到多個本地處理器上,而且可以通過它的multiprocessing.managers對象在網(wǎng)絡(luò)中分散負(fù)載娇哆。它還提供了雙向傳輸湃累,以使進(jìn)程間可以彼此交換信息勃救。
  • 每次考慮在一定時間內(nèi)并行處理一些工作時,最好依靠多進(jìn)程創(chuàng)建(fork)多個作業(yè)治力,以便能夠在多個CPU核之間分散負(fù)載蒙秒。

異步和事件驅(qū)動架構(gòu)

  • 事件驅(qū)動架構(gòu)背后的技術(shù)是事件循環(huán)的建立。程序調(diào)用一個函數(shù)宵统,它會一直阻塞直到收到事件晕讲。其核心思想是令程序在等待輸入輸出完成前保持忙碌狀態(tài),最基本的事件通常類似于“我有數(shù)據(jù)就緒可被讀取”或者“我可以無阻塞地寫入數(shù)據(jù)”
  • 在Unix中马澈,用于構(gòu)建這種事件循環(huán)的標(biāo)準(zhǔn)函數(shù)是系統(tǒng)調(diào)用select(2)或者poll(2)瓢省。它們會對幾個文件描述符進(jìn)行監(jiān)聽,并在其中之一準(zhǔn)備好讀或?qū)憰r做出響應(yīng)箭券。
  • python中有select净捅,asyncio疑枯,pyev

面向服務(wù)架構(gòu)

使用ZeroMQ

RDBMS和ORM

SQLAlchemy PostgreSQL

上下文管理器

  • 上下文管理協(xié)議:

    1. 調(diào)用方法A
    2. 執(zhí)行一段代碼
    3. 調(diào)用方法B
  • with (open) as :執(zhí)行一段代碼

  • 這里希望調(diào)用方法B必須總是在調(diào)用方法A之后辩块。open函數(shù)很好地闡明了這一模式,打開文件并在內(nèi)部分配一個文件描述符的構(gòu)造函數(shù)便是方法A荆永。釋放對應(yīng)文件描述符的close方法就是方法B废亭。顯然,close方法總是應(yīng)該在實例化文件對象之后調(diào)用具钥。

  • contextlib標(biāo)準(zhǔn)庫提供了contextmanager豆村,通過生成器構(gòu)造__enter____exit__方法,從而簡化了這一機(jī)制的實現(xiàn)骂删。

  • 在流水線對象上使用上下文管理器

import contextlib
class Pipeline(object):
    def _publish(self, objects):
        #image publication code here
        pass
    def _flush(self):
        #image flushing code here
        pass
    @contextlib.contextmanager
    def publisher(self):
        try:
            yield self._publish
        finally:
            self._flush()

現(xiàn)在掌动,當(dāng)用戶在使用流水線發(fā)布某些數(shù)據(jù)時,他們無需使用_publish或者_(dá)flush宁玫。用戶只需請求一個使用了名組(eponym)函數(shù)的publisher并使用它粗恢。

pipeline = Pipeline()
with pipeline.publisher() as publisher:
    publisher([1, 2, 3, 4])
    #當(dāng)提供這樣一個API時,就不會遇到用戶錯誤
  • 通過一條with語句同時打開兩個文件
with open("file1", "r") as source, open("file2", "w") as destination:
    destination.write(source.read())
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欧瘪,一起剝皮案震驚了整個濱河市眷射,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌佛掖,老刑警劉巖妖碉,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異芥被,居然都是意外死亡欧宜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門拴魄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冗茸,“玉大人猛拴,你說我怎么就攤上這事∈凑” “怎么了愉昆?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長麻蹋。 經(jīng)常有香客問我跛溉,道長,這世上最難降的妖魔是什么扮授? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任芳室,我火速辦了婚禮,結(jié)果婚禮上刹勃,老公的妹妹穿的比我還像新娘堪侯。我一直安慰自己,他們只是感情好荔仁,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布伍宦。 她就那樣靜靜地躺著,像睡著了一般乏梁。 火紅的嫁衣襯著肌膚如雪次洼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天遇骑,我揣著相機(jī)與錄音卖毁,去河邊找鬼。 笑死落萎,一個胖子當(dāng)著我的面吹牛亥啦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播练链,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼翔脱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了兑宇?” 一聲冷哼從身側(cè)響起碍侦,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隶糕,沒想到半個月后瓷产,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡枚驻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年濒旦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片再登。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡尔邓,死狀恐怖晾剖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情梯嗽,我是刑警寧澤齿尽,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站灯节,受9級特大地震影響循头,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炎疆,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一卡骂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧形入,春花似錦全跨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至崩掘,卻和暖如春七嫌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苞慢。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留英妓,地道東北人挽放。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蔓纠,于是被迫代替她去往敵國和親辑畦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容