Browse Source

Merge pull request #16876 from glassez/blocking

Avoid some blocking calls to libtorrent

Under some conditions (when libtorrent is doing heavy work), blocking calls can wait quite a long time, thereby suspending the main application thread. In some cases, we can avoid this, since we have enough data to make the job without call to libtorrent. Although in some cases it may require a little more work to be done in the main thread, but overall responsiveness still benefits greatly in the end, especially when the libtorrent working thread is heavily loaded.
adaptive-webui-19844
Vladimir Golovnev 3 years ago committed by GitHub
parent
commit
613e9866aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      src/base/bittorrent/session.cpp
  2. 33
      src/base/bittorrent/torrentimpl.cpp

18
src/base/bittorrent/session.cpp

@ -2310,6 +2310,17 @@ bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source
for (int i = 0; i < addTorrentParams.filePriorities.size(); ++i) for (int i = 0; i < addTorrentParams.filePriorities.size(); ++i)
p.file_priorities[LT::toUnderlyingType(nativeIndexes[i])] = LT::toNative(addTorrentParams.filePriorities[i]); p.file_priorities[LT::toUnderlyingType(nativeIndexes[i])] = LT::toNative(addTorrentParams.filePriorities[i]);
if (isAddTrackersEnabled() && !torrentInfo.isPrivate())
{
p.trackers.reserve(static_cast<std::size_t>(m_additionalTrackerList.size()));
p.tracker_tiers.reserve(static_cast<std::size_t>(m_additionalTrackerList.size()));
for (const TrackerEntry &trackerEntry : asConst(m_additionalTrackerList))
{
p.trackers.push_back(trackerEntry.url.toStdString());
p.tracker_tiers.push_back(trackerEntry.tier);
}
}
p.ti = torrentInfo.nativeInfo(); p.ti = torrentInfo.nativeInfo();
} }
else else
@ -4899,7 +4910,7 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle)
const LoadTorrentParams params = m_loadingTorrents.take(torrentID); const LoadTorrentParams params = m_loadingTorrents.take(torrentID);
auto *const torrent = new TorrentImpl {this, m_nativeSession, nativeHandle, params}; auto *const torrent = new TorrentImpl(this, m_nativeSession, nativeHandle, params);
m_torrents.insert(torrent->id(), torrent); m_torrents.insert(torrent->id(), torrent);
const bool hasMetadata = torrent->hasMetadata(); const bool hasMetadata = torrent->hasMetadata();
@ -4918,14 +4929,13 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle)
exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name()); exportTorrentFile(torrentInfo, torrentExportDirectory(), torrent->name());
} }
} }
if (isAddTrackersEnabled() && !torrent->isPrivate())
torrent->addTrackers(m_additionalTrackerList);
} }
if (((torrent->ratioLimit() >= 0) || (torrent->seedingTimeLimit() >= 0)) if (((torrent->ratioLimit() >= 0) || (torrent->seedingTimeLimit() >= 0))
&& !m_seedingLimitTimer->isActive()) && !m_seedingLimitTimer->isActive())
{
m_seedingLimitTimer->start(); m_seedingLimitTimer->start();
}
// Send torrent addition signal // Send torrent addition signal
emit torrentLoaded(torrent); emit torrentLoaded(torrent);

33
src/base/bittorrent/torrentimpl.cpp

@ -284,17 +284,18 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
m_filePaths.reserve(filesCount); m_filePaths.reserve(filesCount);
m_indexMap.reserve(filesCount); m_indexMap.reserve(filesCount);
m_filePriorities.reserve(filesCount); m_filePriorities.reserve(filesCount);
const std::shared_ptr<const lt::torrent_info> currentInfo = m_nativeHandle.torrent_file();
const lt::file_storage &fileStorage = currentInfo->files();
const std::vector<lt::download_priority_t> filePriorities = const std::vector<lt::download_priority_t> filePriorities =
resized(m_ltAddTorrentParams.file_priorities, fileStorage.num_files() resized(m_ltAddTorrentParams.file_priorities, m_ltAddTorrentParams.ti->num_files()
, LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored)); , LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored));
for (int i = 0; i < filesCount; ++i) for (int i = 0; i < filesCount; ++i)
{ {
const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i); const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i);
m_indexMap[nativeIndex] = i; m_indexMap[nativeIndex] = i;
const auto filePath = Path(fileStorage.file_path(nativeIndex)).removedExtension(QB_EXT); const auto fileIter = m_ltAddTorrentParams.renamed_files.find(nativeIndex);
const Path filePath = ((fileIter != m_ltAddTorrentParams.renamed_files.end())
? Path(fileIter->second).removedExtension(QB_EXT) : m_torrentInfo.filePath(i));
m_filePaths.append(filePath); m_filePaths.append(filePath);
const auto priority = LT::fromNative(filePriorities[LT::toUnderlyingType(nativeIndex)]); const auto priority = LT::fromNative(filePriorities[LT::toUnderlyingType(nativeIndex)]);
@ -1465,28 +1466,32 @@ void TorrentImpl::applyFirstLastPiecePriority(const bool enabled)
// Download first and last pieces first for every file in the torrent // Download first and last pieces first for every file in the torrent
std::vector<lt::download_priority_t> piecePriorities = nativeHandle().get_piece_priorities(); auto piecePriorities = std::vector<lt::download_priority_t>(m_torrentInfo.piecesCount(), LT::toNative(DownloadPriority::Ignored));
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it // Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case. // we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
for (int index = 0; index < m_filePriorities.size(); ++index) for (int fileIndex = 0; fileIndex < m_filePriorities.size(); ++fileIndex)
{ {
const DownloadPriority filePrio = m_filePriorities[index]; const DownloadPriority filePrio = m_filePriorities[fileIndex];
if (filePrio <= DownloadPriority::Ignored) if (filePrio <= DownloadPriority::Ignored)
continue; continue;
// Determine the priority to set // Determine the priority to set
const DownloadPriority newPrio = enabled ? DownloadPriority::Maximum : filePrio; const lt::download_priority_t piecePrio = LT::toNative(enabled ? DownloadPriority::Maximum : filePrio);
const auto piecePrio = static_cast<lt::download_priority_t>(static_cast<int>(newPrio)); const TorrentInfo::PieceRange pieceRange = m_torrentInfo.filePieces(fileIndex);
const TorrentInfo::PieceRange extremities = m_torrentInfo.filePieces(index);
// worst case: AVI index = 1% of total file size (at the end of the file) // worst case: AVI index = 1% of total file size (at the end of the file)
const int nNumPieces = std::ceil(fileSize(index) * 0.01 / pieceLength()); const int numPieces = std::ceil(fileSize(fileIndex) * 0.01 / pieceLength());
for (int i = 0; i < nNumPieces; ++i) for (int i = 0; i < numPieces; ++i)
{ {
piecePriorities[extremities.first() + i] = piecePrio; piecePriorities[pieceRange.first() + i] = piecePrio;
piecePriorities[extremities.last() - i] = piecePrio; piecePriorities[pieceRange.last() - i] = piecePrio;
} }
const int firstPiece = pieceRange.first() + numPieces;
const int lastPiece = pieceRange.last() - numPieces;
for (int pieceIndex = firstPiece; pieceIndex <= lastPiece; ++pieceIndex)
piecePriorities[pieceIndex] = LT::toNative(filePrio);
} }
m_nativeHandle.prioritize_pieces(piecePriorities); m_nativeHandle.prioritize_pieces(piecePriorities);

Loading…
Cancel
Save