Эффективный источник okio, поддержанный уже выделенным ByteString?
При использовании OkHttp Websocket слушатель использует ByteString для предоставления двоичной полезной нагрузки приложению. Я хочу передать эти байты в некоторый код, который принимает okio.Source (в данном конкретном случае, GzipSource), но я не могу найти какой-либо хороший способ сделать это эффективно.
Мое текущее решение выглядит так:
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
Buffer gzipBuffer = new Buffer();
gzipBuffer.write(bytes);
GzipSource gzipSource = new GzipSource(gzipBuffer);
....
}
Недостаток этого Buffer.write
заключается в том, что он создает дополнительные байтовые копии (а в случае буфера сегментированные, даже если они объединены в пул), это приводит к дополнительным издержкам). И в этом случае Websocket, байтовый массив был просто выделен для самой ByteString (при передаче из WebSocketReader
осущ).
Мой вопрос: есть ли другой предпочтительный способ чтения с ByteString
через Source
? Так как ByteString
должен быть неизменным и Source
будет просто держать некоторую информацию о положении чтения, я думаю, что это должно быть вполне выполнимо (но не из внешнего кода, так как я не могу получить доступ к byte[]
).. Так что я чувствую, что мне не хватает очевидного решения здесь..:)
Спасибо за любые подсказки или указатели!
1 ответ
То, как вы это написали, почти оптимально.
Okio оптимизирован для перемещения данных между слоями преобразования: сжатие, кадрирование, многопоточность и т. Д. Хотя перемещение данных между слоями происходит очень быстро (без копий), первоначальные затраты на первоначальную загрузку данных в систему очень высоки. Обычно это все, что вам нужно сделать: загрузка файла или отправка пакета. Но в этом случае вам нужно скопировать, чтобы получить байты в первый буфер. Это кажется неэффективным, но положительным моментом является то, что ваш следующий вызов Source.read() будет быстрым, так что в целом все равно будет отличным.