From: "giner (Stanislav German-Evtushenko) via ruby-core" Date: 2023-03-01T23:38:04+00:00 Subject: [ruby-core:112651] [Ruby master Bug#19470] Frequent small range-reads from and then writes to a large array are very slow Issue #19470 has been updated by giner (Stanislav German-Evtushenko). > Do you have any evidence that this problem actually occurs frequently? I cannot say whether this affects many projects. I've encountered this twice so far when optimizing code to reduce memory allocations (by writing to the same array instead of allocating new ones). In both cases it took quite a while to figure out why instead of being faster and using less memory it did the opposite, i.e. became slower and used more memory. ---------------------------------------- Bug #19470: Frequent small range-reads from and then writes to a large array are very slow https://bugs.ruby-lang.org/issues/19470#change-102100 * Author: giner (Stanislav German-Evtushenko) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-linux] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Write to a large array gets very slow when done after range-reading more than 3 items. In such case the original array gets marked as shared which triggers CoW on a small change afterwards. This leads to a significant performance impact and high memory utilization in cases when we need to range-read/write from/to the same array many times. While this issue can be avoided by reading <= 3 elements at a time the main problem is that this behaviour is not obvious and hard to catch on on-trivial projects. ```ruby times = [] arr = [0] * 100000 times.push 0 100000.times do time_start = Time.now arr[5] = 100 # takes 0.01662315899999512 times[-1] += Time.now - time_start end times.push 0 100000.times do arr[0..2] time_start = Time.now arr[5] = 100 # takes 0.01826406799999659 times[-1] += Time.now - time_start end times.push 0 100000.times do arr[0..3] time_start = Time.now arr[5] = 100 # takes 7.757753919000069 times[-1] += Time.now - time_start end times.push 0 100000.times do arr.dup time_start = Time.now arr[5] = 100 # takes 7.626929300999957 times[-1] += Time.now - time_start end times.push 0 100000.times do arr.clone time_start = Time.now arr[5] = 100 # takes 8.216933763000046 times[-1] += Time.now - time_start end p times ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/