#io #julia #buffer
#io #julia #буфер
Вопрос:
У меня есть команда curl, ввод которой я хочу загрузить с помощью BSON. По соображениям производительности я хочу прочитать вывод curl непосредственно в память, не сохраняя его в файл. Кроме того, я хочу закрыть curl как можно скорее, поэтому я хочу прочитать данные из curl, а затем передать их в BSON, у нас были некоторые проблемы, когда curl был открыт, потому что это было быстрее, чем последовательный синтаксический анализ.
Я знаю, что это работает, но он слишком долго держит curl открытым, что вызывает проблемы, когда мы делаем это параллельно много раз одновременно, а сервер, с которого мы загружаем, немного занят.
using BSON
cmd = `curl <some data>`
BSON.load(open(cmd))
Чтобы закрыть cmd
как можно скорее, у меня есть это:
# created IOBuffer to wrap bytes
import BSON.load
function BSON.load(bytes::Vector{UInt8})
io = IOBuffer()
write(io, bytes)
seekstart(io)
BSON.load(io)
end
cmd = `curl <some data>`
BSON.load(read(cmd))
что работает, но я считаю это очень уродливым. Также я не уверен, что это не приводит к некоторому снижению производительности.
Есть ли более элегантный способ сделать это? Могу ли я read(cmd)
ввести некоторую структуру ввода-вывода, которая затем может быть передана BSON.load
?
Я понял, что точно такая же проблема имеет место для Serialization.deserialize
. Мое решение для десериализации такое же, но я приветствую любые улучшения.
Комментарии:
1. Когда вы говорите «но он слишком долго держит curl открытым, что вызывает проблемы, когда мы делаем это параллельно много раз одновременно, а сервер, с которого мы загружаем, немного занят», вы имеете в виду, что BSON.load работает медленнее, чем загрузка, поэтому он блокирует процесс загрузки?
2. Да, точно. Но в основном это происходило во время JSON.parse, где разбор json занимал больше времени, чем загрузка через curl. У нас есть хранилище объектов, которое находится в том же центре обработки данных, что и сервер с Julia, так что это довольно быстро.
Ответ №1:
Немного неясно, что означает ваш вопрос, когда вы говорите, что он «слишком долго держит curl открытым», но вот два разных способа сделать это:
julia> using BSON
julia> url = "https://raw.githubusercontent.com/JuliaIO/BSON.jl/master/test/test.bson"
"https://raw.githubusercontent.com/JuliaIO/BSON.jl/master/test/test.bson"
julia> open(BSON.load, `curl -s $url`)
Dict{Symbol,Any} with 2 entries:
:a => Complex{Int64}[1 2im, 3 4im]
:b => "Hello, World!"
julia> BSON.load(IOBuffer(read(`curl -s $url`)))
Dict{Symbol,Any} with 2 entries:
:a => Complex{Int64}[1 2im, 3 4im]
:b => "Hello, World!"
Первая версия похожа на вашу первую версию, но сразу же закрывает процесс curl после завершения загрузки. Вторая версия считывает результат вызова curl в байтовый вектор, обертывает его в IOBuffer
и затем вызывает BSON.load
для этого.
Комментарии:
1. О,
open(BSON.load,
curl -s $ url)
немедленно закрывается? Это здорово. Просто чтобы быть уверенным, есть ли это где-нибудь в документах? Мне было трудно понять, когда процесс остается открытым до тех пор, пока не будет прочитан весь буфер, и когда он немедленно закрывается.2. Ну, он закрывается сразу после
BSON.load
завершения. В общем случаеopen(f, path)
вызываетf
дескриптор открытого файла, а затем закрывается, независимо от того,f
возвращает или выдает ошибки. Это первый документированный метод,open
если вы это сделаете?open
.3. Да, у нас были проблемы с зависанием curl, когда после него выполнялся последовательный синтаксический анализ, подобный этому, и иногда соединение прерывалось до завершения синтаксического анализа.
4. В этом случае вам, вероятно, понадобится второй, поскольку он сразу считывает все данные в вектор, а затем оборачивает этот вектор в интерфейсе ввода-вывода, чтобы передать его в код синтаксического анализа.
5. Да, точно, я использовал второе решение, и оно решило большинство этих неясных проблем.