a9ec3be2fd845a2f7ebed3031ecc1802d0dc42a3
This automatically makes SGSharedPtr more efficient when used in
standard containers (among others). See below for the benchmark details.
Mark as 'noexcept' (after checking it's legitimate!) the SGSharedPtr and
SGReferenced methods required for SGSharedPtr's move constructor and
move assignment operator to be guaranteed 'noexcept'.
Benchmark
---------
I measured a 25 % speedup with g++ 6.3.0 on Linux amd64, CFLAGS=-Wall -O2
as compared to commit 18f0484249 (which is
just before my changes to SGSharedPtr.hxx) on the following test code,
called with:
nbIterations = 3000000
minSize = 0
maxSize = 200
------------------------------------------------------------------------
static std::default_random_engine randomNumbersGenerator;
class SGReferencedTestClass : public SGReferenced
{ int i; };
void SGSharedPtr_perfTest(std::size_t nbIterations,
std::size_t minSize, std::size_t maxSize)
{
using Ref = SGSharedPtr<SGReferencedTestClass>;
std::uniform_int_distribution<std::size_t> sizeDist(minSize, maxSize);
auto randomSize = std::bind(sizeDist, randomNumbersGenerator);
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
std::vector<Ref> v;
for (std::size_t i=0; i < nbIterations; i++) {
v = std::vector<Ref>{}; // start anew
for (std::size_t j=0; j < randomSize(); j++) {
auto p = Ref(new SGReferencedTestClass());
v.emplace_back(std::move(p));
}
std::shuffle(v.begin(), v.end(), randomNumbersGenerator);
std::sort(v.begin(), v.end());
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsedSecs = end - start;
std::cout << elapsedSecs.count() << "\n"; // duration in seconds
}
------------------------------------------------------------------------
Basically, these gains can be explained by the fact that copying an
SGSharedPtr requires to test SGReferenced::ref, increase the refcount,
and then when the object is destroyed, test again SGReferenced::ref,
decrease the refcount and test it in order to maybe delete. With the
move constructor and move assignment operator, copying the argument is
never necessary: its raw pointer can be swapped with the one contained
in *this, which is very fast. For the move constructor, this is all that
is needed; move assignment just needs one reset() call after that in
order to release the resource from the moved-from shared pointer.
SimGear - Simulator Construction Tools ====================================== http://www.flightgear.org SimGear is a set of open-source libraries designed to be used as building blocks for quickly assembling 3d simulations, games, and visualization applications. SimGear is developed by the FlightGear project and also provides the base for the FlightGear Flight Simulator. Source code for SimGear is released under the GNU Library General Public License (LGPL) - see COPYING for license details. See INSTALL file for help on building SimGear.
Description
Languages
C++
85.5%
C
13.1%
CMake
1.4%