国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

<轉> 從20秒到0.5秒:一個使用Rust語言來優化Python性能的案例

Kahn / 609人閱讀

摘要:的在調查發現問題在于的性能缺陷后,我們決定嘗試解析器的性能,這是為我們的工具編寫的。這意味著即使忽略任何優化,只是將解析器替換為解析器就可以緩解我們的性能瓶頸。

注: 轉自 微信公眾號“高可用架構”:從20秒到0.5秒:一個使用Rust語言來優化Python性能的案例


導讀:Python 被很多互聯網系統廣泛使用,但在另外一方面,它也存在一些性能問題,不過 Sentry 工程師分享的在關鍵模塊上用另外一門語言 Rust 來代替 Python 的情況還是比較罕見,也在 Python 圈引發了熱議,高可用架構小編將文章翻譯轉載如下。

Sentry 是一個幫助在線業務進行監控及錯誤分析的云服務,它每月處理超過十億次錯誤。我們已經能夠擴展我們的大多數系統,但在過去幾個月,Python 寫的 source map 處理程序已經成為我們性能瓶頸所在。(譯者:source map 就是將壓縮或者混淆過的代碼與原始代碼的對應表)

從上周開始,基礎設施團隊決定調查 source map 處理程序的性能瓶頸?!覀兊?Javascript 客戶端已經成為我們最受歡迎的程序,其中一個原因是我們通過 source map 反混淆 JavaScript 的能力。然而,處理操作不是沒有代價的。我們必須獲取,解壓縮,反混淆然后反向擴張,使 JavaScript 堆棧跟蹤可讀。

當我們在 4 年前編寫了原始處理流水線時,source map 生態系統才剛剛開始演化。隨著它成長為一個復雜而成熟的 source map 處理程序,我們花了很多時間用 Python 來處理問題。

截至昨天,我們通過 Rust 模塊替換我們老的 Python 的 souce map 處理模塊,大大減少了處理時間和我們的機器上的 CPU 利用率。

為了解釋這一切,我們需要先理解 source map 和用 Python 的缺點。

Python 的 Source Maps

隨著我們的用戶的應用程序變得越來越復雜,他們的 source map 也越來越復雜。在 Python 中解析 JSON 本身是足夠快的,因為它們只是字符串而已。問題在于反序列化。每個 source map token 產生一個 Python 對象,我們有一些 source map 可能有幾百萬個 token。

將 source map token 反序列化的問題使得我們為基本 Python 對象支付巨大的成本。另外,所有這些對象都參與引用計數和垃圾收集,這進一步增加了開銷。處理 30MB source map 使得單個 Python 進程在內存中擴展到? 800MB,執行數百萬次內存分配,并使垃圾收集器非常忙碌(譯者注:token 是短生命周期對象,有新生代就好多了,這時候就體現出我大 Java 的優勢了)。

由于這種反序列化需要對象頭和垃圾回收機制,我們能在 Python 層做改進的空間非常小。

Rust 的 Source Maps

在調查發現問題在于 Python 的性能缺陷后,我們決定嘗試 Rust source map 解析器的性能,這是為我們的 CLI 工具編寫的。在將 Rust 解析器應用于問題很大的 source map 之后,其表明多帶帶使用該庫進行解析可以將處理時間從 > 20 秒減少到 < 0.5 秒。這意味著即使忽略任何優化,只是將 Python 解析器替換為 Rust 解析器就可以緩解我們的性能瓶頸。

我們證明 Rust 確實更快后,就清理了一些 Sentry 內部 API,以便我們可以用新的庫替換原來的實現。這個 Python 庫命名為 libsourcemap,是我們自己的 Rust source map 的一個薄包裝。

優化結果

部署該庫后,專門用于 source map 處理的機器壓力大大降低。

最糟糕的 source map 處理時間減少到原來的十分之一。

更重要的是,平均處理時間減少到? 400 ms。

JavaScript 是我們最受歡迎的項目語言,這種變化達到了將所有事件的端到端處理時間減少到? 300 ms。

在 Python 中 嵌入 Rust

有很多方法可以暴露 Rust 庫給 Python。我們選擇將 Rust 代碼編譯成一個 dylib,并提供一些 ol"C 函數,通過 CFFI 和 C 頭文件暴露給 Python。有了 C 語言頭文件,CFFI 生成一些 shim( shim 是一個小型的函數庫,用于透明地攔截 API 調用,修改傳遞的參數、自身處理操作、或把操作重定向到其他地方),可以調用 Rust。這樣,libsourcemap 可以打開在運行時從 Rust 生成的動態共享庫。

這個過程有兩個步驟。第一個是在 setup.py 運行時配置 CFFI 的構建模塊:

在構建模塊之后,頭文件通過 C 預處理器來處理,以便擴展宏( CFFI 本身無法執行的過程)。此外,這將告訴 CFFI 在哪里放置生成的 shim 模塊。所有完成的之后,加載模塊:

下一步是編寫一些包裝器代碼來為 Rust 對象提供一個 Python API,這樣能夠轉發異常。這發生在兩個過程中:首先,確保在 Rust 代碼中,我們盡可能使用結果對象。此外,我們需要處理好 panic,以確保他們不會跨越 DLL 邊界。第二,我們定義了一個可以存儲錯誤信息的幫助結構 ; 并將其作為 out 參數傳遞給可能失敗的函數。

在 Python 中,我們提供了一個上下文管理器:

我們有一個特定錯誤類( special_errors)的字典,但如果沒有找到具體的錯誤,將會拋一個通用的 SourceMapError。

從那里,我們實際上可以定義 source map 的基類:

在 Rust 中暴露 C API

我們從包含一些導出函數的 C 頭開始,如何從 Rust 導出它們? 有兩個工具:特殊的# [no_mangle] 屬性和 std :: panic 模塊 ; 提供了 Rust panic 處理器。我們自己建立了一些 helper 來處理這個:一個函數用來通知 Python 發生了一個異常和兩個異常處理 helper,一個通用的,另一個包裝了返回值。有了這個,包裝方法如下:

boxed_landingpad 的工作方式很簡單。它調用閉包,用 panic :: catch_unwind 捕獲 panic,解開結果,并在原始指針中加上成功值。如果發生錯誤,它會填充 err_out 并返回一個 NULL 指針。在 lsm_view_free 中,只需要從原始指針重新構建。

構建擴展

要實際構建擴展,我們必須在 setuptools 中做一些不太優雅的事情。幸運的是,在這件事上我們沒有花太多時間,因為我們已經有一個類似的工具來處理。

這個做法最方便的部分是源代碼用 cargo 編譯,二進制安裝最終的 dylib,消除任何最終用戶使用 Rust 工具鏈的需要。

那些做得好,那些沒做好?

我在 Twitter 上被問到:“ Rust 會有什么替代品?”說實話,Rust 很難替代。原因是,除非你想用性能更好的語言重寫整個 Python 組件,否則只能使用本機擴展。在這種情況下,對語言的要求是相當苛刻的:它不能有一個侵入式運行時,不能有一個 GC,并且必須支持 C ABI?,F在,我認為適合的語言是 C,C++ 和 Rust。

哪方面工作的好:

結合 Rust 和 Python 與 CFFI。有一些替代品,鏈接到 libpython,但構建更復雜。

在老一些的 CentOS 版本使用 Docker 來構建可移植的 Linux 容器。雖然這個過程是乏味的,然而不同的 Linux 發興版和內核之間的穩定性的差異使得 Docker 和 CentOS 成為可接受的構建解決方案。

Rust 生態系統。我們使用 crates.io 的 serde 反序列化和 base64 庫,兩個庫工作非常好。此外,mmap 支持使用由社區 memmap 提供的另一庫。

哪方面工作的不好:

迭代和編譯時間真的可以更好。我們每次更改字符時都編譯模塊和頭文件。

setuptools 步驟非常脆弱。我們可能花了更多的時間來使 setuptools 工作。幸運的是,我們以前做過一次,所以這次更容易。

雖然 Rust 對我們的工作幫助很大,毫無疑問,有很多需要改進。特別是,用于導出 C ABI(并使其對 Python 有用)的基礎設施應該有很大改進空間。編譯時間也不是很長(譯者的話,不是很長的意思是可能夠我沏杯茶,懷念 go 的編譯速度)。希望增量編譯將有所幫助。

下一步

其實我們還有更多的改進空間。我們可以以更高效的格式啟動緩存,比如一組存儲在內存中的結構體而不是使用解析 JSON。特別是,如果與文件系統緩存配對,我們幾乎可以完全消除加載的成本,因為我們平分了索引,這可以使用 mmap 非常有效。

鑒于這個好的結果,我們很可能會評估 Rust 更多在未來處理一些 CPU 密集型的業務。然而,對于大多數其他操作,程序花更多的時間等待 IO。

小結

雖然這個項目取得了巨大的成功,但是我們只花了很少的時間來實現。它降低了我們的處理時間,它也將幫助我們水平擴展。Rust 一直是這個工作的完美工具,因為它允許我們將昂貴的操作使用本地庫完成,而且不必使用 C 或 C ++(這不太適合這種復雜的任務)。雖然很容易在 Rust 中編寫 source map 解析器,但是使用 C / C++ 來完成的話,代碼更多,且沒那么有意思。

我們確實喜歡 Python,并且是許多 Python 開源計劃的貢獻者。雖然 Python 仍然是我們最喜歡的語言,但我們相信在合適的地方使用合適的語言。Rust 被證明是這項工作的最佳工具,我們很高興看到 Rust 和 Python 將來會帶給我們什么。

譯者注:不熟悉 source map 的同學請看阮一峰的這篇文章 http://www.ruanyifeng.com/blo...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44207.html

相關文章

  • 模型領域GPU性能排名

    圖示為GPU性能排行榜,我們可以看到所有GPU的原始相關性能圖表。同時根據訓練、推理能力由高到低做了排名。我們可以看到,H100 GPU的8位性能與16位性能的優化與其他GPU存在巨大差距。針對大模型訓練來說,H100和A100有絕對的優勢首先,從架構角度來看,A100采用了NVIDIA的Ampere架構,而H100則是基于Hopper架構。Ampere架構以其高效的圖形處理性能和多任務處理能力而...

    UCloud小助手 評論0 收藏0
  • pythontime控制模塊時間格式與結構型時長詳細說明

      文中關鍵闡述了pythontime控制模塊時間格式與結構型時長的基本知識,文中為大家介紹得非常詳盡,對大家學習知識和工作具有很強的參照參考意義,必須的小伙伴可以借鑒一下  time控制模塊  1:簡述  時間表示方法的種類  時間格式  格式化硬盤的時間也字符串數組  結構型時長  時間格式:時間格式表述的是以1970年1月1日整0點至目前秒偏移,數據類型是字符型,主要是用于讓電子計算機看得 ...

    89542767 評論0 收藏0
  • Python繪制折線圖可視化神器pyecharts案例

      小編寫這篇文章的主要目的,主要是用來進行繪制折線圖,在繪制的時候,用到的是Python這門語言,主要應用到的技能是Python pyecharts,利用它去進行繪制折線圖,下面小編就以案例的形式,去給大家詳細的做個介紹?! ∏把浴 ∠嘈庞泻芏嗟男』锇榭戳巳绱硕鄠€案例之后肯定有所發現,每一個案例都對應著每一個配置,如果是官方配置文檔,說實話看起來真的很難,這樣通過案例實現來解決各種參數的配置,我...

    89542767 評論0 收藏0
  • 壓縮20M文件301優化過程

    摘要:壓縮文件從秒到秒的優化過程有一個需求需要將前端傳過來的張照片,然后后端進行處理以后壓縮成一個壓縮包通過網絡流傳輸出去。源碼如下使用映射文件開始時間內存中的映射文件打印如下可以看到速度和使用的速度差不多的。 壓縮20M文件從30秒到1秒的優化過程 有一個需求需要將前端傳過來的10張照片,然后后端進行處理以后壓縮成一個壓縮包通過網絡流傳輸出去。之前沒有接觸過用Java壓縮文件的,所以就直接...

    niuxiaowei111 評論0 收藏0
  • 怎么利用Python實現一鍵將頭像成動漫風?

      Python的用處還是比較的大的,在工作當中,方方面面的都會遇到使用Python這門技能。那么,怎么實現圖形之間的轉換呢?比如,將我們平常的頭像,轉換成為動漫風格的呢?下面就給大家詳細解答下?! ∽罱贕ithub上面有看到將頭像轉化成動漫風的項目,但是對于不少沒有技術背景的同學來說可能就不知道該怎么使用了,小編今天制作了一個UI界面,大家可以通過一鍵點擊就實現頭像照片轉化成動漫風格的功能。 ...

    89542767 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<