Parallel versus sequential assignment is microbenchmark (not representative) and scales with number of inputs
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 42/100
- Tipo di issue
- Documentazione
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Ferma
- Stack tecnologico
- ruby
- Ambito
- documentation, performance
Direzione di ricerca
Esamina code/general/assignment.rb e la relativa presentazione in README, quindi confronta le affermazioni del benchmark con gli esempi e le misurazioni riportati in questa issue. Determina se il benchmark debba essere rimosso o corredato da annotazioni dettagliate e verifica che la documentazione risultante non presenti più il confronto come ampiamente rappresentativo.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Update: Parallel assignment doesn't allocate unless it's the last statement in a method/proc. There's a benchmark provided below. I'm
I think this benchmark https://github.com/fastruby/fast-ruby/blob/main/code/general/assignment.rb needs to be removed or at least heavily annotated on the readme. It is not representative of real code. In my experience, removing parallel assignments into sequential ones speeds up apps.
One reason is that parallel assignments [can] allocate an intermediate array [if it is the last statement in a method for example], the other is that the benchmark uses MANY assignments and the performance difference seems to scale with assignment numbers. In the wild the most common number is 2.
Also worth noting that by using integers, we're isolating to only the assignment time (mostly) but this distorts the possible impact of the code. If you switch to strings that allocate then the pressure on the GC actually causes sequential assignment to be faster (at least sometimes).
Benchmarks below.
Reasoning
In https://github.com/fastruby/fast-ruby/blob/main/code/general/assignment.rb it states that parallel assignment is much faster than sequential assignment, but if you have only 2 assignments, the difference is negligible:
require 'benchmark/ips'
def fast
_a, _b= 1, 2
nil
end
def slow
_a = 1
_b = 2
nil
end
Benchmark.ips do |x|
x.report('Parallel Assignment') { fast }
x.report('Sequential Assignment') { slow }
x.compare!
end
Warming up --------------------------------------
Parallel Assignment 1.494M i/100ms
Sequential Assignment
1.344M i/100ms
Calculating -------------------------------------
Parallel Assignment 14.659M (± 4.9%) i/s - 73.229M in 5.007646s
Sequential Assignment
15.020M (± 4.0%) i/s - 75.261M in 5.019081s
Comparison:
Sequential Assignment: 15019526.2 i/s
Parallel Assignment: 14658684.7 i/s - same-ish: difference falls within error
Note that sequential assignment is faster here (but within error). While the parallel assignment is fewer operations, it also introduces an intermediate array that requires an allocation:
$ cat scratch.rb
require 'memory_profiler'
report = MemoryProfiler.report do
_a, _b = 1, 2
end
report.pretty_print
⛄️ 3.1.2 🚀 /tmp
$ ruby scratch.rb
Total allocated: 40 bytes (1 objects)
Total retained: 40 bytes (1 objects)
allocated memory by gem
-----------------------------------
40 other
allocated memory by file
-----------------------------------
40 scratch.rb
allocated memory by location
-----------------------------------
40 scratch.rb:3
allocated memory by class
-----------------------------------
40 Array
# ...
[Note that the above only works because the parallel assignment is returned
_a, _b = 1, 2; nildoes not allocate]
Even in the case of MANY sequential versus parallel assignments, if the function is doing anything non-trivial (such as allocating strings as opposed to using integers which are all singletons, then the effect of the "faster" parallel assignment is pretty much negligible. This run actually has sequential being faster:
require 'benchmark/ips'
def fast
_a, _b, _c, _d, _e, _f, _g, _h = String.new("1"), String.new("2"), String.new("3"), String.new("4"), String.new("5"), String.new("6"), String.new("7"), String.new("8")
nil
end
def slow
_a = String.new("1")
_b = String.new("2")
_c = String.new("3")
_d = String.new("4")
_e = String.new("5")
_f = String.new("6")
_g = String.new("7")
_h = String.new("8")
nil
end
Benchmark.ips do |x|
x.report('Parallel Assignment') { fast }
x.report('Sequential Assignment') { slow }
x.compare!
end
Warming up --------------------------------------
Parallel Assignment 80.318k i/100ms
Sequential Assignment
77.943k i/100ms
Calculating -------------------------------------
Parallel Assignment 796.245k (± 3.7%) i/s - 4.016M in 5.050973s
Sequential Assignment
767.116k (± 5.9%) i/s - 3.897M in 5.099053s
Comparison:
Parallel Assignment: 796245.3 i/s
Sequential Assignment: 767115.8 i/s - same-ish: difference falls within error
The sequential assignment is also faster here (but within error).
- Lingua principale
- Ruby
- Stelle
- 5.7k
- Fork
- 370
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di fastruby/fast-ruby
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 52/100
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 32/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 45/100
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 30/100
Tutte le issue di fastruby/fast-ruby
Issue simili
-
SyncEm always forwards a dummy block, so wrapped methods lose their no-block/Enumerator behavior Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
bug P2
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
dependabot
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
githubnext/gh-aw-cao#13349 ·
-
user-reported
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
Kong/developer.konghq.com#7316 ·