Ich versuche, einen Leistungsunterschied zwischen der Verwendung von Boost.Variant und der Verwendung von virtuellen Schnittstellen zu messen. Angenommen, ich möchte verschiedene Typen von Zahlen gleichmäßig erhöhen, indem ich Boost.Variant verwende. Ich würde eine boost :: variant über int und float und einen statischen Besucher verwenden, der jeden einzelnen erhöht. Mit Klassenschnittstellen würde ich eine reine virtuelle Klassennummer und number_int- und number_float-Klassen verwenden, die daraus abgeleitet sind und eine "increment" -Methode implementieren.
Aus meinen Tests ist die Verwendung von Schnittstellen viel schneller als die Verwendung von Boost.Variant. lief ich den Code unten und erhielt diese Ergebnisse:
Virtuelle: 00: 00: 00.001028
Variant: 00: 00: 00,012081
Boost.Variant Vs Virtual Interface Leistung
Warum glauben Sie, ist dieser Unterschied? Ich dachte Boost.Variant wäre viel schneller.
** Hinweis: Normalerweise verwendet Boost.Variant Heap-Zuordnungen, um zu gewährleisten, dass die Variante immer nicht leer ist. Aber ich lese in der Boost.Variant Dokumentation, dass, wenn boost :: has_nothrow_copy true ist, es keine Heap-Zuweisungen verwendet, die Dinge wesentlich schneller machen sollten. Für int und float boost :: has_nothrow_copy ist true.
Hier ist mein Code zum Messen der beiden Ansätze gegeneinander.
#include <iostream>
#include <boost/variant/variant.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/format.hpp>
const int iterations_count = 100000;
// a visitor that increments a variant by N
template <int N>
struct add : boost::static_visitor<> {
template <typename T>
void operator() (T& t) const {
t += N;
}
};
// a number interface
struct number {
virtual void increment() = 0;
};
// number interface implementation for all types
template <typename T>
struct number_ : number {
number_(T t = 0) : t(t) {}
virtual void increment() {
t += 1;
}
T t;
};
void use_virtual() {
number_<int> num_int;
number* num = &num_int;
for (int i = 0; i < iterations_count; i++) {
num->increment();
}
}
void use_variant() {
typedef boost::variant<int, float, double> number;
number num = 0;
for (int i = 0; i < iterations_count; i++) {
boost::apply_visitor(add<1>(), num);
}
}
int main() {
using namespace boost::posix_time;
ptime start, end;
time_duration d1, d2;
// virtual
start = microsec_clock::universal_time();
use_virtual();
end = microsec_clock::universal_time();
// store result
d1 = end - start;
// variant
start = microsec_clock::universal_time();
use_variant();
end = microsec_clock::universal_time();
// store result
d2 = end - start;
// output
std::cout <<
boost::format(
"Virtual: %1%\n"
"Variant: %2%\n"
) % d1 % d2;
}
Vielen Dank für die Buchung der Follow-up, mich interessiert! –
Was waren Ihre Ergebnisse und welcher Compiler? Mit Boost 1.52 und Mingw 4.7 bekomme ich eine Variante, die im Release-Modus ungefähr 8-mal langsamer ist. Seltsamerweise ist "-O2" etwas schneller als "-O3";/ – AbstractDissonance
Ich benutze g ++ 4.7 und ich bin mir nicht sicher, welche Boost Version es ist, aber es ist wahrscheinlich 1.5x. Ich übergab -O2 an den Compiler und meine Ergebnisse waren: Virtual: 00: 00: 00.018806 Variante: 00: 00: 00.000001 Die meisten Male würde ich 00:00:00 auf der Variante bekommen, so dass ich iterations_count auf 10000000 setzen Ich führe diesen Test auf einer 2.8GHz Intel Core i7 CPU durch. –