Hi all!
There are 3 tests detailed in this mail:
1. ExternalResource garbage collector performance
2. Isolate/Context performance comparisons
3. Isolate/Context memory usage comparisons
1. ExternalResource garbage collector performance:
I messed up the ExternalResource test I had sent to Jędrek before
so here is a new test case (external-resource-tester.cpp). I used a
helper class for measuring which I also attached to this mail
(tester.h, tester.cpp). A sample run with 100 test cases:
Mean of ExternalResource : 22.34 ms.
Deviation of ExternalResource : 0.19 ms.
Number of Point objects : 0.
Mean of MakeWeak : 33.82 ms.
Deviation of MakeWeak : 0.32 ms.
Number of Point objects : 0.
2. Isolate/Context memory usage comparisons:
We used a Valgrind tool called Freya (see
http://webkit.sed.hu/node/29) to measure the memory consumption of the
test cases.
The test cases use greatly simplified Engine-like classes as follows:
- Using an own Context and the default Isolate (context-memtest.cpp)
- Using an own Context and an own Isolate (isolate-memtest.cpp)
- Using an own Isolate and no Context at all (pure-isolate-memtest.cpp)
We tested each cases with 1, 5, 10 and 15 instances of test objects.
The results are:
- context-memtest 1: 984.0Kb, 5: 1.7Mb, 10: 2.5Mb, 15: 2.9Mb
- isolate-memtest 1: 1.4Mb, 5: 4.1Mb, 10: 7.6Mb, 15: 11.1Mb
- pure-isolate-memtest 1: 796.0Kb, 5: 788.0Kb, 10: 792.0Kb, 15: 792.0Kb
3. Isolate/Context performance comparisons:
These tests are also use simplified Engine-like classes as the
ones in the memory benchmarks and the same Tester class as the
ExternalResource test (isolate-context-tester.cpp, tester.h,
tester.cpp). A sample run with 100 test cases:
Mean:
Own Isolate : 34.86 ms
Default Isolate : 5.47 ms
Pure Isolate : 30.26 ms
Deviation:
Own Isolate : 0.21 ms
Default Isolate : 0.02 ms
Pure Isolate : 0.18 ms
Best regards:
Szeged Team
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
/*
* Benchmark - ExternalResource
* Usage: external-resource-tester [number_of_tests]
*
*/
#include <v8.h>
#include <cstdlib>
#include "tester.h"
using namespace v8;
using namespace std;
class Point {
public:
static int counter;
Point(int x, int y) : x_(x), y_(y)
{
++counter;
}
~Point()
{
--counter;
}
int x_;
int y_;
};
int Point::counter = 0;
class V8ObjectResource : public v8::Object::ExternalResource {
public:
V8ObjectResource() {}
enum ResourceType { POINT_TYPE, SOME_OTHER_TYPE };
virtual ResourceType getResourceType() const = 0;
};
class V8PointResource : public V8ObjectResource {
public:
V8PointResource(Point* p) : point(p) {}
~V8PointResource()
{
delete point;
}
enum { V8_RESOURCE_TYPE = V8ObjectResource::POINT_TYPE };
V8ObjectResource::ResourceType getResourceType() const
{
return V8ObjectResource::POINT_TYPE;
}
private:
Point* point;
};
template <class T>
inline T* v8_resource_cast(Handle<Object> object)
{
V8ObjectResource* resource = static_cast<V8ObjectResource*>(object->GetExternalResource());
return (resource &&
(uint32_t)resource->getResourceType() == (uint32_t)T::V8_RESOURCE_TYPE) ? static_cast<T*>(resource) : 0;
}
void weakPointCallback(Persistent<Value> object, void* parameter)
{
Point* point = static_cast<Point*>(parameter);
delete point;
object.Dispose();
object.Clear();
}
void MeasureExternalResource(int counter, Tester* tester)
{
v8::Handle<v8::ObjectTemplate> point_templ = v8::ObjectTemplate::New();
point_templ->SetHasExternalResource(true);
Point* p;
V8PointResource* point_resource;
{
HandleScope inner_scope;
Persistent<Object> obj;
for (int i = 0; i < counter; ++i) {
p = new Point(i, i + 1);
point_resource = new V8PointResource(p);
obj = Persistent<Object>::New(point_templ->NewInstance());
obj->SetExternalResource(point_resource);
obj.Dispose();
}
}
tester->startMeasuring();
while (!V8::IdleNotification()) { }
tester->endMeasuring();
}
void MeasureMakeWeak(int counter, Tester* tester)
{
v8::Handle<v8::ObjectTemplate> point_templ = v8::ObjectTemplate::New();
point_templ->SetInternalFieldCount(1);
Persistent<Object> obj;
Point* point;
{
HandleScope embedded_scope;
for (int i = 0; i < counter; ++i) {
point = new Point(i, i + 1);
obj = Persistent<Object>::New(point_templ->NewInstance());
obj->SetInternalField(0, External::New(point));
obj.MakeWeak(point, weakPointCallback);
}
}
tester->startMeasuring();
while (!V8::IdleNotification()) { }
tester->endMeasuring();
}
int main(int argc, char* argv[])
{
if (argc > 2) {
return 666;
}
int number_of_tests = 1;
if (argc == 2) {
int num = atoi(argv[1]);
if (num) {
number_of_tests = num;
} else {
return 666;
}
}
HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
Persistent<Context> context = Context::New(NULL, global);
Context::Scope context_scope(context);
const int OBJECT_COUNTER = 100000;
Tester* externalTester = new Tester();
Tester* weakTester = new Tester();
for (int i = 0; i < number_of_tests; ++i) {
MeasureExternalResource(OBJECT_COUNTER, externalTester);
MeasureMakeWeak(OBJECT_COUNTER, weakTester);
}
printf("Mean of ExternalResource : %.2lf ms.\n", externalTester->getMean());
printf("Deviation of ExternalResource : %.2lf ms.\n", externalTester->getDeviation());
printf("Number of Point objects : %d.\n", Point::counter);
printf("Mean of MakeWeak : %.2lf ms.\n", weakTester->getMean());
printf("Deviation of MakeWeak : %.2lf ms.\n", weakTester->getDeviation());
printf("Number of Point objects : %d.\n", Point::counter);
context.Dispose();
return 0;
}
#ifndef TESTER_H
#define TESTER_H
#include <vector>
#include <iterator>
#include <sys/time.h>
using namespace std;
class Tester {
public:
Tester();
~Tester();
void startMeasuring();
void endMeasuring();
int getNumberOfTests() const;
double getMean() const;
double getVariance() const;
double getDeviation() const;
double getLastResult() const;
typedef vector<double>::const_iterator tester_iterator;
tester_iterator begin();
tester_iterator end();
void clear();
private:
double getTimeDiff();
Tester(const Tester&);
Tester& operator=(const Tester&);
vector<double>* m_results;
struct timeval m_start;
struct timeval m_end;
double m_startTime;
double m_endTime;
};
#endif
#include "tester.h"
#include <cmath>
Tester::Tester()
{
m_results = new vector<double>();
}
Tester::~Tester()
{
delete m_results;
}
void Tester::startMeasuring()
{
gettimeofday(&m_start, NULL);
}
void Tester::endMeasuring()
{
gettimeofday(&m_end, NULL);
m_results->push_back(getTimeDiff());
}
double Tester::getLastResult() const
{
return m_results->back();
}
int Tester::getNumberOfTests() const
{
return m_results->size();
}
double Tester::getMean() const
{
double sum = 0;
for (vector<double>::iterator it = m_results->begin();
it != m_results->end(); ++it) {
sum += *it;
}
return sum / m_results->size();
}
double Tester::getVariance() const
{
double variance_numerator = 0;
for (vector<double>::iterator it = m_results->begin();
it != m_results->end(); ++it) {
variance_numerator += pow(*it - getMean(), 2);
}
return variance_numerator / m_results->size();
}
double Tester::getDeviation() const
{
return sqrt(getVariance());
}
Tester::tester_iterator Tester::begin()
{
return m_results->begin();
}
Tester::tester_iterator Tester::end()
{
return m_results->end();
}
void Tester::clear()
{
m_results->clear();
}
double Tester::getTimeDiff()
{
m_startTime = m_start.tv_sec * 1000000 + m_start.tv_usec;
m_endTime = m_end.tv_sec * 1000000 + m_end.tv_usec;
return (m_endTime - m_startTime) / 1000;
}
/*
* Benchmark - Isolate/Context performance
* Usage: isolate-context-benchmark [number_of_tests]
*/
#include <v8.h>
#include <cstdlib>
#include "tester.h"
using namespace v8;
using namespace std;
class EngineWithPureIsolate {
public:
EngineWithPureIsolate()
{
m_isolate = Isolate::New();
}
~EngineWithPureIsolate()
{
m_isolate->Dispose();
}
void doStuff()
{
m_isolate->Enter();
m_isolate->Exit();
}
private:
Isolate* m_isolate;
};
class EngineWithOwnIsolate {
public:
EngineWithOwnIsolate()
{
m_isolate = Isolate::New();
m_isolate->Enter();
m_context = Context::New();
m_isolate->Exit();
}
~EngineWithOwnIsolate()
{
m_isolate->Enter();
m_context.Dispose();
m_isolate->Exit();
m_isolate->Dispose();
}
void doStuff()
{
m_isolate->Enter();
m_context->Enter();
m_context->Exit();
m_isolate->Exit();
}
private:
EngineWithOwnIsolate(const EngineWithOwnIsolate&);
EngineWithOwnIsolate& operator=(const EngineWithOwnIsolate&);
Isolate* m_isolate;
Persistent<Context> m_context;
};
class EngineWithDefaultIsolate {
public:
EngineWithDefaultIsolate()
{
m_context = Context::New();
}
~EngineWithDefaultIsolate()
{
m_context.Dispose();
}
void doStuff()
{
m_context->Enter();
m_context->Exit();
}
private:
EngineWithDefaultIsolate(const EngineWithDefaultIsolate&);
EngineWithDefaultIsolate& operator=(const EngineWithDefaultIsolate&);
Persistent<Context> m_context;
};
int main(int argc, char* argv[])
{
if (argc > 2) {
return 666;
}
int number_of_tests = 1;
if (argc == 2) {
int num = atoi(argv[1]);
if (num) {
number_of_tests = num;
} else {
return 666;
}
}
HandleScope scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
Handle<Value> result;
const int NUMBER_OF_LOOPS = 100000;
EngineWithOwnIsolate* engine_with_own_isolate = new EngineWithOwnIsolate();
EngineWithDefaultIsolate* engine_with_default_isolate = new EngineWithDefaultIsolate();
EngineWithPureIsolate* engine_with_pure_isolate = new EngineWithPureIsolate();
Tester* ownIsolateTester = new Tester();
for (int i = 0; i < number_of_tests; ++i) {
ownIsolateTester->startMeasuring();
for (int i = 0; i < NUMBER_OF_LOOPS; ++i) {
engine_with_own_isolate->doStuff();
}
ownIsolateTester->endMeasuring();
}
Tester* defaultIsolateTester = new Tester();
for (int i = 0; i < number_of_tests; ++i) {
defaultIsolateTester->startMeasuring();
for (int i = 0; i < NUMBER_OF_LOOPS; ++i) {
engine_with_default_isolate->doStuff();
}
defaultIsolateTester->endMeasuring();
}
Tester* pureIsolateTester = new Tester();
for (int i = 0; i < number_of_tests; ++i) {
pureIsolateTester->startMeasuring();
for (int i = 0; i < NUMBER_OF_LOOPS; ++i) {
engine_with_pure_isolate->doStuff();
}
pureIsolateTester->endMeasuring();
}
printf("Mean:\n");
printf("Own Isolate : %.2lf ms\n", ownIsolateTester->getMean());
printf("Default Isolate : %.2lf ms\n", defaultIsolateTester->getMean());
printf("Pure Isolate : %.2lf ms\n", pureIsolateTester->getMean());
printf("Deviation:\n");
printf("Own Isolate : %.2lf ms\n", ownIsolateTester->getDeviation());
printf("Default Isolate : %.2lf ms\n", defaultIsolateTester->getDeviation());
printf("Pure Isolate : %.2lf ms\n", pureIsolateTester->getDeviation());
delete engine_with_own_isolate;
delete engine_with_default_isolate;
delete engine_with_pure_isolate;
context.Dispose();
return 0;
}
/*
* Benchmark - Isolate/Context
* Usage: context-memtest [number_of_engines]
*
*/
#include <v8.h>
#include <vector>
#include <cstdlib>
using namespace v8;
using namespace std;
class EngineWithDefaultIsolate {
public:
EngineWithDefaultIsolate()
{
m_context = Context::New();
}
~EngineWithDefaultIsolate()
{
m_context.Dispose();
}
private:
EngineWithDefaultIsolate(const EngineWithDefaultIsolate&);
EngineWithDefaultIsolate& operator=(const EngineWithDefaultIsolate&);
Persistent<Context> m_context;
};
int main(int argc, char* argv[])
{
if (argc > 2) {
return 666;
}
int number_of_engines = 1;
if (argc == 2) {
int num = atoi(argv[1]);
if (num) {
number_of_engines = num;
} else {
return 666;
}
}
HandleScope scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
vector<EngineWithDefaultIsolate* >* engines = new vector<EngineWithDefaultIsolate* >();
for (int i = 0; i < number_of_engines; ++i) {
engines->push_back(new EngineWithDefaultIsolate());
}
for (vector<EngineWithDefaultIsolate*>::iterator it = engines->begin();
it != engines->end();
++it) {
delete *it;
}
delete engines;
context.Dispose();
return 0;
}
/*
* Benchmark - Isolate/Context
* Usage: isolate-memtest [number_of_engines]
*
*/
#include <v8.h>
#include <vector>
#include <cstdlib>
using namespace v8;
using namespace std;
class EngineWithOwnIsolate {
public:
EngineWithOwnIsolate()
{
m_isolate = Isolate::New();
m_isolate->Enter();
m_context = Context::New();
m_isolate->Exit();
}
~EngineWithOwnIsolate()
{
m_isolate->Enter();
m_context.Dispose();
m_isolate->Exit();
m_isolate->Dispose();
}
private:
EngineWithOwnIsolate(const EngineWithOwnIsolate&);
EngineWithOwnIsolate& operator=(const EngineWithOwnIsolate&);
Isolate* m_isolate;
Persistent<Context> m_context;
};
int main(int argc, char* argv[])
{
if (argc > 2) {
return 666;
}
int number_of_engines = 1;
if (argc == 2) {
int num = atoi(argv[1]);
if (num) {
number_of_engines = num;
} else {
return 666;
}
}
HandleScope scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
vector<EngineWithOwnIsolate* >* engines = new vector<EngineWithOwnIsolate* >();
for (int i = 0; i < number_of_engines; ++i) {
engines->push_back(new EngineWithOwnIsolate());
}
for (vector<EngineWithOwnIsolate*>::iterator it = engines->begin();
it != engines->end();
++it) {
delete *it;
}
delete engines;
context.Dispose();
return 0;
}
/*
* Benchmark - Isolate/Context
* Usage: pure-isolate-memtest [number_of_engines]
*
*/
#include <v8.h>
#include <vector>
#include <cstdlib>
using namespace v8;
using namespace std;
class EngineWithPureIsolate {
public:
EngineWithPureIsolate()
{
m_isolate = Isolate::New();
}
~EngineWithPureIsolate()
{
m_isolate->Dispose();
printf("Destructor\n");
}
private:
EngineWithPureIsolate(const EngineWithPureIsolate&);
EngineWithPureIsolate& operator=(const EngineWithPureIsolate&);
Isolate* m_isolate;
};
int main(int argc, char* argv[])
{
if (argc > 2) {
return 666;
}
int number_of_engines = 1;
if (argc == 2) {
int num = atoi(argv[1]);
if (num) {
number_of_engines = num;
} else {
return 666;
}
}
HandleScope scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
vector<EngineWithPureIsolate* >* engines = new vector<EngineWithPureIsolate* >();
for (int i = 0; i < number_of_engines; ++i) {
engines->push_back(new EngineWithPureIsolate());
}
for (vector<EngineWithPureIsolate*>::iterator it = engines->begin();
it != engines->end();
++it) {
delete *it;
}
delete engines;
context.Dispose();
return 0;
}
_______________________________________________
Qt-script mailing list
[email protected]
http://lists.qt.nokia.com/mailman/listinfo/qt-script