From 44df10d6cbfc7ab03a04fa13695dc2abadcb27c7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 26 Feb 2019 19:31:33 +0400 Subject: [PATCH] Improve working with cache in streaming. --- .../streaming/media_streaming_player.cpp | 6 +- .../streaming/media_streaming_reader.cpp | 66 ++++++++++++------- .../media/streaming/media_streaming_reader.h | 1 + 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp index c281cf6c80..493d7507af 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp @@ -137,6 +137,7 @@ void Player::trackReceivedTill( } } +static auto wakes = 0; template void Player::trackPlayedTill( const Track &track, @@ -152,6 +153,7 @@ void Player::trackPlayedTill( if (_pauseReading && !bothReceivedEnough(kLoadInAdvanceFor)) { _pauseReading = false; _file->wake(); + ++wakes; } } @@ -417,7 +419,8 @@ bool Player::trackReceivedEnough( const TrackState &state, crl::time amount) const { return FullTrackReceived(state) - || (state.position + amount <= state.receivedTill); + || (state.position != kTimeUnknown + && state.position + amount <= state.receivedTill); } bool Player::bothReceivedEnough(crl::time amount) const { @@ -569,6 +572,7 @@ Player::~Player() { // // So instead of maintaining it in the class definition as well we // simply call stop() here, after that the destruction is trivial. + LOG(("WAKES: %1").arg(wakes)); stop(); } diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp index b4b47af102..b60f49fa0c 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp @@ -357,19 +357,15 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult { && (fromSlice + 1 == tillSlice || fromSlice + 2 == tillSlice) && tillSlice <= _data.size()); + const auto cacheNotLoaded = [&](int sliceIndex) { + return (_headerMode != HeaderMode::NoCache) + && (_headerMode != HeaderMode::Unknown) + && !(_data[sliceIndex].flags & Flag::LoadedFromCache); + }; const auto handlePrepareResult = [&]( int sliceIndex, const Slice::PrepareFillResult &prepared) { - if (sliceIndex == _data.size()) { - return; - } - if (!(_data[sliceIndex].flags & Flag::LoadedFromCache) - && _headerMode != HeaderMode::NoCache - && _headerMode != HeaderMode::Unknown) { - if (!(_data[sliceIndex].flags & Flag::LoadingFromCache)) { - _data[sliceIndex].flags |= Flag::LoadingFromCache; - result.sliceNumbersFromCache.add(sliceIndex + 1); - } + if (cacheNotLoaded(sliceIndex)) { return; } for (const auto offset : prepared.offsetsFromLoader.values()) { @@ -379,7 +375,16 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult { } } }; - + const auto handleReadFromCache = [&](int sliceIndex) { + if (cacheNotLoaded(sliceIndex) + && !(_data[sliceIndex].flags & Flag::LoadingFromCache)) { + _data[sliceIndex].flags |= Flag::LoadingFromCache; + if (sliceIndex == 23) { + int a = 0; + } + result.sliceNumbersFromCache.add(sliceIndex + 1); + } + }; const auto firstFrom = offset - fromSlice * kInSlice; const auto firstTill = std::min(kInSlice, till - fromSlice * kInSlice); const auto secondFrom = 0; @@ -389,7 +394,9 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult { ? _data[fromSlice + 1].prepareFill(secondFrom, secondTill) : Slice::PrepareFillResult(); handlePrepareResult(fromSlice, first); - handlePrepareResult(fromSlice + 1, second); + if (fromSlice + 1 < tillSlice) { + handlePrepareResult(fromSlice + 1, second); + } if (first.ready && second.ready) { markSliceUsed(fromSlice); CopyLoaded( @@ -405,18 +412,13 @@ auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult { secondFrom, secondTill); } - if (_usedSlices.size() > kSlicesInMemory - && _headerMode != HeaderMode::Unknown) { - const auto purgeSlice = _usedSlices.front(); - _usedSlices.pop_front(); - if (_headerMode == HeaderMode::NoCache - || !(_data[purgeSlice].flags & Flag::ChangedSinceCache)) { - _data[purgeSlice] = Slice(); - } else { - result.toCache = serializeAndUnloadSlice(purgeSlice + 1); - } - } + result.toCache = serializeAndUnloadUnused(); result.filled = true; + } else { + handleReadFromCache(fromSlice); + if (fromSlice + 1 < tillSlice) { + handleReadFromCache(fromSlice + 1); + } } return result; } @@ -442,6 +444,24 @@ int Reader::Slices::maxSliceSize(int sliceNumber) const { : _size; } +Reader::SerializedSlice Reader::Slices::serializeAndUnloadUnused() { + if (_headerMode == HeaderMode::Unknown + || _usedSlices.size() <= kSlicesInMemory) { + return {}; + } + const auto purgeSlice = _usedSlices.front(); + _usedSlices.pop_front(); + if (!(_data[purgeSlice].flags & Slice::Flag::LoadedFromCache)) { + // If the only data in this slice was from _header, just leave it. + return {}; + } else if (_headerMode == HeaderMode::NoCache + || !(_data[purgeSlice].flags & Slice::Flag::ChangedSinceCache)) { + _data[purgeSlice] = Slice(); + return {}; + } + return serializeAndUnloadSlice(purgeSlice + 1); +} + Reader::SerializedSlice Reader::Slices::serializeAndUnloadSlice( int sliceNumber) { Expects(sliceNumber >= 0 && sliceNumber <= _data.size()); diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h index 040a6fcce5..eac09d0449 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h @@ -127,6 +127,7 @@ private: void applyHeaderCacheData(); int maxSliceSize(int sliceNumber) const; SerializedSlice serializeAndUnloadSlice(int sliceNumber); + SerializedSlice serializeAndUnloadUnused(); void markSliceUsed(int sliceIndex); std::vector _data;