From 4e2daf117b3d79cc12b8779f752a4d7a4355c676 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 24 Jan 2022 13:28:56 +0800 Subject: [PATCH] Speed up bitfields conversion The old code took 3~5 times longer than the newer version. --- src/base/CMakeLists.txt | 2 + src/base/base.pri | 2 + src/base/bittorrent/ltqbitarray.cpp | 59 +++++++++++++++++++++++++++++ src/base/bittorrent/ltqbitarray.h | 38 +++++++++++++++++++ src/base/bittorrent/peerinfo.cpp | 9 +---- src/base/bittorrent/torrentimpl.cpp | 11 +----- 6 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 src/base/bittorrent/ltqbitarray.cpp create mode 100644 src/base/bittorrent/ltqbitarray.h diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index f4e79d266..49b3bf336 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(qbt_base STATIC bittorrent/filterparserthread.h bittorrent/infohash.h bittorrent/loadtorrentparams.h + bittorrent/ltqbitarray.h bittorrent/ltqhash.h bittorrent/lttypecast.h bittorrent/magneturi.h @@ -108,6 +109,7 @@ add_library(qbt_base STATIC bittorrent/filesearcher.cpp bittorrent/filterparserthread.cpp bittorrent/infohash.cpp + bittorrent/ltqbitarray.cpp bittorrent/magneturi.cpp bittorrent/nativesessionextension.cpp bittorrent/nativetorrentextension.cpp diff --git a/src/base/base.pri b/src/base/base.pri index 63196cfe1..169844c5e 100644 --- a/src/base/base.pri +++ b/src/base/base.pri @@ -16,6 +16,7 @@ HEADERS += \ $$PWD/bittorrent/filterparserthread.h \ $$PWD/bittorrent/infohash.h \ $$PWD/bittorrent/loadtorrentparams.h \ + $$PWD/bittorrent/ltqbitarray.h \ $$PWD/bittorrent/ltqhash.h \ $$PWD/bittorrent/lttypecast.h \ $$PWD/bittorrent/magneturi.h \ @@ -108,6 +109,7 @@ SOURCES += \ $$PWD/bittorrent/filesearcher.cpp \ $$PWD/bittorrent/filterparserthread.cpp \ $$PWD/bittorrent/infohash.cpp \ + $$PWD/bittorrent/ltqbitarray.cpp \ $$PWD/bittorrent/magneturi.cpp \ $$PWD/bittorrent/nativesessionextension.cpp \ $$PWD/bittorrent/nativetorrentextension.cpp \ diff --git a/src/base/bittorrent/ltqbitarray.cpp b/src/base/bittorrent/ltqbitarray.cpp new file mode 100644 index 000000000..b965da70c --- /dev/null +++ b/src/base/bittorrent/ltqbitarray.cpp @@ -0,0 +1,59 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Mike Tzou (Chocobo1) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "ltqbitarray.h" + +#include + +#include + +#include + +namespace +{ + unsigned char reverseByte(const unsigned char byte) + { + // https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits + return (((byte * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL) >> 32; + } +} + +namespace BitTorrent::LT +{ + QBitArray toQBitArray(const lt::bitfield &bits) + { + const char *bitsData = bits.data(); + const int dataLength = (bits.size() + 7) / 8; + + auto tmp = std::make_unique(dataLength); + for (int i = 0; i < dataLength; ++i) + tmp[i] = reverseByte(bitsData[i]); + + return QBitArray::fromBits(tmp.get(), bits.size()); + } +} diff --git a/src/base/bittorrent/ltqbitarray.h b/src/base/bittorrent/ltqbitarray.h new file mode 100644 index 000000000..427bfca47 --- /dev/null +++ b/src/base/bittorrent/ltqbitarray.h @@ -0,0 +1,38 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2022 Mike Tzou (Chocobo1) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#pragma once + +#include + +class QBitArray; + +namespace BitTorrent::LT +{ + QBitArray toQBitArray(const lt::bitfield &bits); +} diff --git a/src/base/bittorrent/peerinfo.cpp b/src/base/bittorrent/peerinfo.cpp index 291459434..0e04f5460 100644 --- a/src/base/bittorrent/peerinfo.cpp +++ b/src/base/bittorrent/peerinfo.cpp @@ -30,6 +30,7 @@ #include +#include "base/bittorrent/ltqbitarray.h" #include "base/bittorrent/torrent.h" #include "base/net/geoipmanager.h" #include "base/unicodestrings.h" @@ -207,13 +208,7 @@ qlonglong PeerInfo::totalDownload() const QBitArray PeerInfo::pieces() const { - QBitArray result(m_nativeInfo.pieces.size()); - for (int i = 0; i < result.size(); ++i) - { - if (m_nativeInfo.pieces[lt::piece_index_t {i}]) - result.setBit(i, true); - } - return result; + return LT::toQBitArray(m_nativeInfo.pieces); } QString PeerInfo::connectionType() const diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index f929fc47c..6f689401a 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -58,6 +58,7 @@ #include "common.h" #include "downloadpriority.h" #include "loadtorrentparams.h" +#include "ltqbitarray.h" #include "ltqhash.h" #include "lttypecast.h" #include "peeraddress.h" @@ -1250,15 +1251,7 @@ QVector TorrentImpl::peers() const QBitArray TorrentImpl::pieces() const { if (m_pieces.isEmpty()) - { - m_pieces.resize(m_nativeStatus.pieces.size()); - for (int i = 0; i < m_pieces.size(); ++i) - { - if (m_nativeStatus.pieces[lt::piece_index_t(i)]) - m_pieces.setBit(i, true); - } - } - + m_pieces = LT::toQBitArray(m_nativeStatus.pieces); return m_pieces; }