PyPy 和 CPython 的效能比較測試
最近我在維基百科上完成了一些資料探勘的任務。它由這些部分組成:
解析enwiki-pages-articles.xml的維基百科轉儲;
把類別和頁儲存到MongoDB裡面;
對類別名稱重新分門別類別。
我對CPython 2.7.3和PyPy 2b的實際任務表現進行了測試。我使用的函式庫是:
redis 2.7.2
pymongo 2.4.2
此外CPython是由以下函式庫支援的:
hiredis
pymongo c-extensions到會從PyPy得到多大好處(何況CPython的資料庫驅動是C寫的)。
下面我會描述一些有趣的結果。
抽取維基頁名
我需要在所有維基百科的類別中建立維基頁名到page.id的聯接並儲存重新分配的它們。最簡單的解決方案應該是匯入enwiki-page.sql(定義了一個RDB表)到MySQL裡面,然後傳輸資料、進行重新分配。但我不想增加MySQL需求(有骨氣!XD)所以我用純Python寫了一個簡單的SQL插入語句解析器,然後直接從enwiki-page.sql導入數據,進行重新分配。
這個任務對CPU依賴更大,所以我再次看好PyPy。
/ time
PyPy 169.00s 使用者態8.52s 系統態90% CPU
CPython 1287.13s 用戶態8.10s 接態96% CPU
id.筆記本的記憶體太小了,不能儲存供我測試的資訊了)。從enwiki.xml中篩選類別
為了方便工作,我需要從enwiki-pages-articles.xml中過濾類別,並將它們存儲相同的XML格式的類別。因此我選用了SAX解析器,在PyPy和CPython中都適用的包裝器解析。對外的原生編譯套件(同事在PyPy和CPython 中) 。
class WikiCategoryHandler(handler.ContentHandler): """Class which detecs category pages and stores them separately """ ignored = set(('contributor', 'comment', 'meta')) def __init__(self, f_out): handler.ContentHandler.__init__(self) self.f_out = f_out self.curr_page = None self.curr_tag = '' self.curr_elem = Element('root', {}) self.root = self.curr_elem self.stack = Stack() self.stack.push(self.curr_elem) self.skip = 0 def startElement(self, name, attrs): if self.skip>0 or name in self.ignored: self.skip += 1 return self.curr_tag = name elem = Element(name, attrs) if name == 'page': elem.ns = -1 self.curr_page = elem else: # we don't want to keep old pages in memory self.curr_elem.append(elem) self.stack.push(elem) self.curr_elem = elem def endElement(self, name): if self.skip>0: self.skip -= 1 return if name == 'page': self.task() self.curr_page = None self.stack.pop() self.curr_elem = self.stack.top() self.curr_tag = self.curr_elem.tag def characters(self, content): if content.isspace(): return if self.skip == 0: self.curr_elem.append(TextElement(content)) if self.curr_tag == 'ns': self.curr_page.ns = int(content) def startDocument(self): self.f_out.write("<root>\n") def endDocument(self): self.f_out.write("<\root>\n") print("FINISH PROCESSING WIKIPEDIA") def task(self): if self.curr_page.ns == 14: self.f_out.write(self.curr_page.render()) class Element(object): def __init__(self, tag, attrs): self.tag = tag self.attrs = attrs self.childrens = [] self.append = self.childrens.append def __repr__(self): return "Element {}".format(self.tag) def render(self, margin=0): if not self.childrens: return u"{0}<{1}{2} />".format( " "*margin, self.tag, "".join([' {}="{}"'.format(k,v) for k,v in {}.iteritems()])) if isinstance(self.childrens[0], TextElement) and len(self.childrens)==1: return u"{0}<{1}{2}>{3}</{1}>".format( " "*margin, self.tag, "".join([u' {}="{}"'.format(k,v) for k,v in {}.iteritems()]), self.childrens[0].render()) return u"{0}<{1}{2}>\n{3}\n{0}</{1}>".format( " "*margin, self.tag, "".join([u' {}="{}"'.format(k,v) for k,v in {}.iteritems()]), "\n".join((c.render(margin+2) for c in self.childrens))) class TextElement(object): def __init__(self, content): self.content = content def __repr__(self): return "TextElement" def render(self, margin=0): return self.content
我曾經想要計算一個有趣的類別集合——在我的一個應用背景下,以Computing類別衍生的一些類別為開始進行計算。為此我需要建立一個提供類別的類別圖——子類別關係圖。
這個任務使用MongoDB作為資料來源,並對結構進行重新分配。演算法是:
for each category.id in redis_categories (it holds *category.id -> category title mapping*) do: title = redis_categories.get(category.id) parent_categories = mongodb get categories for title for each parent_cat in parent categories do: redis_tree.sadd(parent_cat, title) # add to parent_cat set title
如果我們有redis_tree資料庫,僅剩的問題就是遍歷Computing類別下所有可實現的結點了。為避免循環遍歷,我們需要記錄已造訪過的結點。自從我想測試Python的資料庫效能,我就用再分配集合列來解決這個問題。
CPython 44.20s 用戶態13.86s 系統總計 71% CPU list(禁止列表)-來避免進入不需要的類別。但那不是本文的重點。
任務幾乎都是資料庫操作,而CPython有一些加速的亂七八糟的C語言模組。 PyPy不使用這些,但結果卻更快!
我的全部工作需要大量的周期,所以我真高興能用PyPy。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

VS Code可以在Windows 8上運行,但體驗可能不佳。首先確保系統已更新到最新補丁,然後下載與系統架構匹配的VS Code安裝包,按照提示安裝。安裝後,注意某些擴展程序可能與Windows 8不兼容,需要尋找替代擴展或在虛擬機中使用更新的Windows系統。安裝必要的擴展,檢查是否正常工作。儘管VS Code在Windows 8上可行,但建議升級到更新的Windows系統以獲得更好的開發體驗和安全保障。

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

VS Code 擴展存在惡意風險,例如隱藏惡意代碼、利用漏洞、偽裝成合法擴展。識別惡意擴展的方法包括:檢查發布者、閱讀評論、檢查代碼、謹慎安裝。安全措施還包括:安全意識、良好習慣、定期更新和殺毒軟件。
