2010-11-09 7 views
2

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

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

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, это может быть сбор мусора, чтобы высвободить некоторую память.

Что такое накладные расходы для этого сценария? Любые альтернативы?

ответ

1

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

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

+0

Загрузка данных в куски по-прежнему будет хранить все объекты в памяти до тех пор, пока используется «огромная» переменная. –

+0

Но ваш процесс итеративен, поэтому вам не нужно хранить весь «огромный» в памяти, не так ли? – glebm

+0

Истина для этого случая. –

2

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

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

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