Estoy tratando de medir una diferencia de rendimiento entre el uso de Boost.Variant y el uso de interfaces virtuales. Por ejemplo, supongamos que quiero incrementar diferentes tipos de números de manera uniforme, usando Boost.Variant. Utilizaría una variante boost :: sobre int y float y un visitante estático que incrementa cada uno de ellos. Usando interfaces de clase, utilizaría un número de clase virtual puro y las clases number_int y number_float que derivan de él e implementaría un método de "incremento".
Según mis pruebas, el uso de interfaces es mucho más rápido que usar Boost.Variant. Me corrió el código en la parte inferior y recibieron estos resultados:
virtual: 00: 00: 00,001028
Variante: 00: 00: 00,012081
Boost.Variant Vs Virtual Interface Performance
¿Por qué cree que esta diferencia es? Pensé que Boost.Variant sería mucho más rápido.
** Nota: generalmente Boost.Variant usa asignaciones de montón para garantizar que la variante siempre estará no vacía. Pero leí en la documentación de Boost.Variant que si boost :: has_nothrow_copy es verdadero, entonces no usa asignaciones de montón que deberían hacer las cosas significativamente más rápidas. Para int y float boost :: has_nothrow_copy es verdadero.
Aquí está mi código para medir los dos enfoques uno contra el otro.
#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;
}
Gracias por publicar el seguimiento, yo estaba interesado! –
¿Cuáles fueron sus resultados y qué compilador? Utilizando Boost 1.52 y Mingw 4.7 obtengo la variante siendo aproximadamente 8 veces más lenta en el modo de lanzamiento. Curiosamente, '-O2' es ligeramente más rápido que' -O3';/ – AbstractDissonance
Estoy usando g ++ 4.7 y no estoy seguro de qué versión de Boost, pero probablemente sea 1.5x. Pasé -O2 al compilador y mis resultados fueron: Virtual: 00: 00: 00.018806 Variante: 00: 00: 00.000001 La mayoría de las veces obtengo 00:00:00 en la variante, así que establezco iterations_count en 10000000 Estoy ejecutando esta prueba en una CPU Intel Core i7 de 2.8Ghz. –