Какова стоимость WeakRef в Ruby? - PullRequest
2 голосов
/ 09 ноября 2010

Мне интересно, какие издержки при использовании WeakRef при обработке большого набора данных?

Задача, которую я хочу выполнить, выглядит примерно так:

huge = get_array_of_weak_refs # 100000000 entries or more :)
result = huge.length * huge.inject(0) { |accum, it| accum += it.total } # much more complicated, just a sample

Предполагая, что get_array_of_weak_refs не занимает много времени и имеет O(1) сложность.Таким образом, единственное беспокойство вызывает размер памяти массива huge.

В настоящий момент меня не волнует время, необходимое для вычисления result.

.huge - это обычный массив, тогда, конечно, он может просто не поместиться в памяти.

Но поможет ли это, если WeakRef будет использоваться в качестве элементов этого массива?Чтобы после перебора элемента x его можно было собрать, чтобы освободить память.

Каковы издержки для этого сценария?Есть альтернативы?

Ответы [ 2 ]

2 голосов
/ 11 января 2011

Стоимость WeakRef может быть очень высокой.WeakRef расширяет класс Delegator, а в реализации 1.8 объекты Delegator очень тяжелые.Каждый раз, когда вы создаете экземпляр Delegator, каждый метод в обернутом объекте переопределяется.Обтекание строки с делегатором выделит ~ 2800 объектов и использует ~ 90 КБ памяти.Это делает WeakRef непригодным для использования во многих случаях, поскольку они создаются очень медленно и могут использовать больше памяти для объектов, на которые они указывают.

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

Если вы хотите использовать слабые ссылки, вы можете использовать ref gem (https://rubygems.org/gems/ref). Этот драгоценный камень сокращает накладные расходы до <1K памятипо ссылке. Если вы используете Jruby или Rubinius, реализации будут еще более эффективными. </p>

1 голос
/ 09 ноября 2010

Почему вы используете здесь слабые ссылки? Они не помогут, и не предназначены для такого сценария.

Вместо этого установите итератор (объект, который отвечает на each), который загружает данные в виде фрагментов.

...