2014-09-18 4 views
2

Я написал сценарий для рекурсивной загрузки через контейнеры облачных контейнеров Rackspace и получения копии каждого файла, поэтому у меня есть локальная резервная копия, если Rackspace попадает в метеоры и/или hindenbugs.Ошибка утечки памяти тумана

Однако мой сценарий, по-видимому, пропускает память в линейном масштабе при загрузке моих файлов.

В принципе у меня есть метод, который выглядит следующим образом:

def download_file(fog_file, destination_path) 
    data = fog_file.body 
    File.open(destination_path, 'w') { |f| f.write(data) } 
end 

Я понимаю, что в связи с характером тумана, я не могу избежать загрузки всего файла в память, но я бы предположил, что Руби освободить память (или иметь возможность выпускать память) после каждого вызова download_file. В конце концов, переменная data выходит за рамки.

К сожалению, когда я смотрю на мой системный мониторинг, использование памяти просто увеличивается с линейным темпом до тех пор, пока не расходует всю доступную память, после чего сбой сценария.

Что я здесь делаю неправильно?

Я использую Ruby 2.1.2 на Ubuntu.

+1

Не знаете, почему вы просачиваетесь (сохраняете ли вы ссылку на fog_file?), Но вы можете загружать файлы с загрузкой тумана (см. Http://www.kylev.com/2013/05/14/foggy-sponges-and- котята/например) –

+0

Ruby построил сборку мусора после do/end блока относительно File.open. Попробуйте явно закрыть файл и посмотреть, поможет ли это. – Anthony

ответ

1

Вы можете избежать загрузки всего файла в память двумя способами.

Во-первых, вы можете получить файл в 100kb (или меньше) Патроны:

service = Fog::Storage.new({ provider: 'Rackspace', 
          # ... auth config 
          connection_options: {chunk_size: 102_400} # 100 KB in bytes       
}) 

directory = service.directories.get "dir" 

File.open((destination_path, 'w') do | f | 
    directory.files.get("my_file_on_cloud.png") do | data, remaining, content_length | 
    f.syswrite data 
    end 
end 

Во-вторых, вы можете получить файл URL с туманом используйте OpenUri, чтобы загрузить и сохранить файл:

require 'open-uri' 

file = open(file.public_url).read 
File.open(destination_path, 'w') { |f| f.write(file) } 

Первый метод записывает непосредственно в файл назначения, второй вместо этого создает экземпляр Tempfile (создайте временный файл в файловой системе). Попробуйте оба.

+0

Это старый вопрос, и я решил проблему, используя первый метод. Имейте в виду, что chunk_size (по крайней мере для Rackspace) занимает байты не мегабайт, поэтому 0.100, вероятно, не будет работать. Я использовал 'connection_options: {chunk_size: 20_971_520}' для получения 20 мегабайт за раз. Он разрешил проблему утечки. –

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