2015-01-21 2 views
6

У меня есть сложный объект, my_object, который я MARSHAL сMashalling в Руби 2.2.0 медленнее, чем 2.1.5

Marshal.dump (my_object)

Я протестированные производительность вызова, что линия 100 раз в обоих 2.1.5p273 и 2.2.0, и ниже приведены результаты:

2.1.5 
        user  system  total  real 
Marshal Dump 7.310000 0.120000 7.430000 ( 8.988470) 
Marshal Dump 7.520000 0.050000 7.570000 ( 8.210356) 
Marshal Dump 7.610000 0.050000 7.660000 ( 8.432685) 

2.2.0 
        user  system  total  real 
Marshal Dump 26.480000 0.150000 26.630000 (29.591742) 
Marshal Dump 24.100000 0.300000 24.400000 (28.520397) 
Marshal Dump 26.210000 0.210000 26.420000 (29.993412) 

(. Я побежал тест 3 раза для каждой версии, чтобы быть полным)

Как вы можете видеть, это взяв i n превышение в 3 раза в 2.2.0 против 2.1.5. Я отключил Marshal.dump, потому что, используя ruby-prof gem, он показал мне, что это была линия, которая плохо работала; но я не могу найти способ получить методы, которые сам Marshal.dump вызывает в профилировщике.

Edit: увидеть мой ответ с минимальным Repro, нашел после долгих экспериментов

+1

Для тех, кто хочет следовать этому, я уменьшил его до минимального уровня и зарегистрировал его здесь: https://bugs.ruby-lang.org/issues/10761. Проблема, похоже, не является размером, а сложностью, поскольку мне пришлось создать объект с множеством уровней вложенных объектов внутри него, чтобы воспроизвести проблему. – davej

+1

Как вы отредактировали то, что устранило исходный вопрос, и этот вопрос ... ну, это не вопрос, это в основном ответ. Я думаю, что все это интересно, но для стандартов SO я думаю, что он заслуживает понижения. – iain

+0

@ian: Действительно? Мое решение заключалось в том, чтобы оставить вопрос, который никому не помог, или опубликовать то, что, я бы сказал, довольно большое дело или удалить весь вопрос. Я сделал то, что, по моему мнению, было лучше всего для сообщества. Честно говоря, это мелочность, подобная твоей, которая дает выродкам плохую репутацию. – davej

ответ

4

Расположение источника nil.

Marshal.method(:dump).source_location 
#=> nil 

Это означает, что это внедренный метод C, и больше нет кода Ruby, который вы можете отслеживать. Другими словами, это атомно-элементарный метод.

Если вы считаете, что ваш результат верен, тогда я предлагаю вам опубликовать его как ошибку в Ruby trunk. Для новейших версий Ruby действительно найдено несколько проблем с производительностью, поэтому ваш случай не выглядит необычным.

+0

спасибо за технику и предложение. Теперь начинается поиск, чтобы найти крошечную воспроизводимую версию проблемы! – davej

1

Это маршаллинг поплавков, который вызывает замедление.

require 'benchmark' 

class ToBeMarshaled 

    def initialize n 
    @a = [] 
    n.times do |i| 
     @a << i.to_f 
    end 
    end 

end 

tbm = ToBeMarshaled.new(10000) 

n = 100 

Benchmark.bm do |x| 
    x.report("Marshal Dump") {for i in 1..n; Marshal.dump(tbm); end} 
end 

результаты (побежал тестов в 3 раза для каждой версии Ruby):

2.1.5 
        user  system  total  real 
Marshal Dump 0.640000 0.010000 0.650000 ( 0.744080) 
Marshal Dump 0.670000 0.000000 0.670000 ( 0.758597) 
Marshal Dump 0.650000 0.020000 0.670000 ( 0.747583) 

2.2.0 
        user  system  total  real 
Marshal Dump 25.070000 0.220000 25.290000 (27.980023) 
Marshal Dump 24.100000 0.160000 24.260000 (26.633049) 
Marshal Dump 24.440000 0.230000 24.670000 (27.540826) 

~ 35 раз медленнее.

Если взять ".to_f" от этого кода, вы получите:

2.1.5 
        user  system  total  real 
Marshal Dump 0.160000 0.000000 0.160000 ( 0.180247) 
Marshal Dump 0.180000 0.000000 0.180000 ( 0.189485) 
Marshal Dump 0.160000 0.010000 0.170000 ( 0.191304) 

2.2.0 
        user  system  total  real 
Marshal Dump 0.120000 0.010000 0.130000 ( 0.146710) 
Marshal Dump 0.130000 0.010000 0.140000 ( 0.159851) 
Marshal Dump 0.130000 0.000000 0.130000 ( 0.143917) 

2.2.0 слегка вытесняет 2.1.5.

Смежные вопросы