我正在用 python 設計一個延遲敏感的應用程式,其中我將有幾個時間戳陣列。我正在嘗試計算事件在過去 1、5、25、50 和 100 秒內的出現次數,因此總共有 5 個陣列。我計劃在事件發生時將這些陣列附加到事件的時間。然后在一個單獨的執行緒中,我將洗掉早于過去 1、5、25、50 或 100 秒的值。
我希望通常每 100 秒發生少于 1000 次,但理論上的最大值是每 100 秒 10,000 次。我打算使用基本的日期時間物件陣列,但我有興趣了解哪些資料結構對此更快。起初,我正在考慮使用熊貓資料框,但事實證明這太慢了。我知道 numpy 陣列并使用 time.time() 代替,但我想還有其他可能更有效的方法。很想從 Python 專家那里聽到什么方法的計算效率最高。
uj5u.com熱心網友回復:
每秒 10-100 次發生真的不算什么。簡單地使用串列應該很快。我可能只會使用 1 個串列。在這種情況下使用 5 個集合似乎有點矯枉過正,真的不值得。
一方面是寫性能,另一方面是讀性能。除非您需要每秒讀取一百萬次,否則只需遍歷串列并計算其中的值就可以了。
還有一個提示:您可能希望將時間戳存盤為數字(Unix 時間戳,自 1970-01-01 以來的秒數)。并且當您進行閱讀時,不要每次比較都獲取當前時間戳。首先獲取當前時間戳,將其保存到區域變數中,然后與該區域變數進行比較。像這樣:
curr_time = time.time()
for t in times:
sec_ago = t - curr_time
...
即使CPython是相對,當涉及到簡單的回圈,比較,等速度慢,性能仍然應該是你的情況還不錯,我猜。但是,如果你真的需要極致性能,可以考慮實施一些更加“本土化” C,Rust,Cython,等。
嘗試一下!
uj5u.com熱心網友回復:
一個優先級佇列(heapq)將讓你保持時間戳的順序,完成執行緒執行。堆插入是O(log(n)). 從排序堆中洗掉最舊的專案可以通過使用字典進行O(1)或常量時間查找來完成。
如果您使用陣列并在執行緒完成執行時附加時間戳,則必須定期鎖定陣列以防止附加操作,然后使用 ( O(nlog(n))) 洗掉最舊的專案。從概念上講,這可能更簡單,但整體運行需要更長的時間。特別是如果你這樣做了數千或數百萬次。
timeit與任何方法一起使用都是分析您使用的任何資料結構的插入、查找和洗掉的好方法。
uj5u.com熱心網友回復:
這是另一種方法。
如果您將時間戳記為整數(從 epoch 開始的秒數),那么您可以直接使用大小陣列2^31 - 1 - minimum_timestamp作為完美的哈希表。
使用具有完美散列函式的陣列可以O(n)節省記憶體,只需要空間。它很快,只需要O(1)恒定的插入(寫入)和查詢(讀取)時間。
的值minimum_timestamp是您需要跟蹤事件的最小時間戳。這通常是當前時間,除非您需要更早地跟蹤過去的事件。
2^31 - 1此處使用的值是因為這是從 epoch 開始的秒的最大值,因此該解決方案至少可以作業到 2038 年,在最壞的情況下minimum_timestamp為零,即最早可以追溯到 1970 年。
這個陣列的所有元素都被初始化為0并對應于觀察到的事件數量。
陣列中的每個索引都對應于 之后的時間點minimum_timestamp。
當事件發生在時間點n(零索引,從紀元開始以秒為單位)時,索引n處的陣列增加 1,通過減法2^31 - 1 - n使索引增加。
您可以保留一個current_timestamp值,其中current_timestamp > minimum_timestamp 100. 要讀取最后 1、5、25、50 和 100 秒的資料,您只需從current_timestamp這些值中減去,即可獲得讀入陣列所需的索引。
當您的執行緒處理事件時,您會current_timestamp在讀取或查詢陣列時定期更新。
這不是特定于 Python 的,但如果您想從基于 Python 的方法中獲得最佳性能,您可以使用 Cython 來管理底層資料和查找。
添加到串列的末尾(“陣列”)相對便宜,除非增長的串列需要調整大小。用于查詢的排序串列很昂貴。一個完美的哈希表將幫助您避免排序,如果您可以根據唯一索引重新考慮您的資料到預先分配的陣列中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/318187.html
上一篇:從嵌套串列填充字典
