最近在做一些事情時,我開始思考 Ruby 中陣列和范圍的效率。我開始嘗試研究這個,但找不到關于它的資訊,甚至我自己如何測驗它。
所以我遇到了一些檢查 HTTP 狀態碼在什么范圍內的代碼,它是這樣寫的
SUCCESS = (200...300)
REDIRECTION = (300...400)
if SUCCESS.include?(status_code)
status = 'success'
elsif REDIRECTION.include?(status_code)
status = 'redirection'
end
所以這讓我想到,當我們基本上只需要 200...207 時,使用 200...300 似乎很浪費,但是這是否會有很大的效率差異,如果有的話?
還有 4XX 代碼呢,因為它并不總是范圍的直線運行,這讓我想到也許我應該把它變成一個陣列,所以我可以用兩種方式之一來寫它
作為一個直線范圍
CLIENT_ERROR = (400...429)
或作為陣列
CLIENT_ERROR = [*(400...419), 422, 429]
我假設第一個選項是一種更好的方法和更有效的方法,但不太確定如何驗證我的想法,所以對此的任何建議或輸入將不勝感激
uj5u.com熱心網友回復:
TL;博士
范圍通常比具體化陣列更快且記憶體效率更高。但是,具體用例可能會有所不同。
如果有疑問,請進行基準測驗。您可以使用 irb 相對較新的measure命令,或使用Benchmark 模塊來比較和對比不同的方法。通常,將 Range 物體化為 Array 會占用更多記憶體,并且比與 Range(甚至是 Range 物件的小陣列)進行比較要慢,但除非您大量回圈此代碼,否則這似乎是過早的優化。
基準
使用 Ruby 3.1.0,Range 方法在我的系統上快了大約 3,655.77%。例如:
require 'benchmark'
n = 100_000
Benchmark.bmbm do
_1.report("Range") do
n.times do
client_error = [200..299, 400..499]
client_error.include? 404
end
end
_1.report("Array") do
n.times do
client_error = [*(200..299), *(400..499)]
client_error.include? 404
end
end
end
Rehearsal -----------------------------------------
Range 0.022570 0.000107 0.022677 ( 0.022832)
Array 0.707742 0.041499 0.749241 ( 0.750012)
-------------------------------- total: 0.771918sec
user system total real
Range 0.020184 0.000043 0.020227 ( 0.020245)
Array 0.701911 0.037541 0.739452 ( 0.740037)
雖然使用 Jruby 和 TruffleRuby 的總體總時間更好,但使用 Ranges 方法之間的性能差異僅快 3-7 倍。同時,Ruby 3.0.1 顯示使用未具體化的 Range 而不是 Array 的速度提高了大約 37 倍,因此無論哪種方式,Range 方法都是明顯的贏家。
您的具體值將根據系統規格、系統負載以及 Ruby 版本和引擎而有所不同。對于較小的n值,我無法想象它會產生任何實際差異,但您絕對應該針對自己的系統進行基準測驗,以確定果汁是否值得擠壓。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/411417.html
標籤:
