JS speed - Konq vs. Mozilla
Koos Vriezen
koos.vriezen at xs4all.nl
Sun Sep 8 22:23:23 BST 2002
On Sun, 8 Sep 2002, Dirk Mueller wrote:
> On Sam, 07 Sep 2002, Koos Vriezen wrote:
>
> > Still, I'm not sure why its faster. Maybe its the 'Collector::collect()'
> > that's faster in the next run (less blocks).
>
> Profilling the collect() step, it seems the biggest problem is the massive
> amount of cache misses it produces, that is over 78% of all (of testkhtml).
Has collect() the most impact on the speed? I had the impression it was
allocate(int size).
> It might be better to put the ValueImp flags into a separate, continuous
> memory region, because the current pointer following causes it to refetch
> all allocated memory regions into the CPU cache, which is extremely slow.
> Also, as the allocated regions are a multiple of the cache association size,
> this currently screams for caching problems.
>
> Do you want to try that (allocating a separate bitarray for those flags) ?
Hmmm, looked at it but it's not easy. If I change 'int ValueImpl::_flags'
to eg. 'char* ValueImpl::_flags' that points to an array element in a
Block, I can't do this for ValueImp that are on the stack. This happens in
khtml/ecma/kjs_window.cpp ScheduledAction::ScheduledAction.
Maybe you can check the cache misses with the attached patch. I survives
the for loop bench :).
Unfortunately, collect() calls the virtual ValueImpl::mark() on those
that can be deleted, causing these cache misses still in one loop (_flags
is checked in four loops).
Koos
-------------- next part --------------
Index: value.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/value.cpp,v
retrieving revision 1.14
diff -u -3 -p -r1.14 value.cpp
--- value.cpp 2002/06/19 08:21:00 1.14
+++ value.cpp 2002/09/08 21:19:46
@@ -42,34 +42,35 @@ using namespace KJS;
// ----------------------------- ValueImp -------------------------------------
ValueImp::ValueImp() :
- refcount(0),
+ refcount(0)
// Tell the garbage collector that this memory block corresponds to a real object now
- _flags(VI_CREATED)
+ //_flags(VI_CREATED)
{
+ *_flags = VI_CREATED;
//fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
}
ValueImp::~ValueImp()
{
//fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
- _flags |= VI_DESTRUCTED;
+ *_flags |= VI_DESTRUCTED;
}
void ValueImp::mark()
{
//fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
- _flags |= VI_MARKED;
+ *_flags |= VI_MARKED;
}
bool ValueImp::marked() const
{
- return (_flags & VI_MARKED);
+ return (*_flags & VI_MARKED);
}
void ValueImp::setGcAllowed()
{
//fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
- _flags |= VI_GCALLOWED;
+ *_flags |= VI_GCALLOWED;
}
void* ValueImp::operator new(size_t s)
Index: value.h
===================================================================
RCS file: /home/kde/kdelibs/kjs/value.h,v
retrieving revision 1.16
diff -u -3 -p -r1.16 value.h
--- value.h 2002/06/19 08:21:00 1.16
+++ value.h 2002/09/08 21:19:46
@@ -133,7 +133,9 @@ namespace KJS {
}; // VI means VALUEIMPL
ValueImpPrivate *_vd;
- unsigned int _flags;
+ //unsigned int _flags;
+ char * _flags;
+ ValueImp(const ValueImp&);
};
/**
Index: collector.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/collector.cpp,v
retrieving revision 1.34
diff -u -3 -p -r1.34 collector.cpp
--- collector.cpp 2002/09/05 15:51:38 1.34
+++ collector.cpp 2002/09/08 21:19:46
@@ -40,6 +40,7 @@ namespace KJS {
int filled;
ValueImp** mem;
CollectorBlock *prev, *next;
+ char *flags;
};
}; // namespace
@@ -50,7 +51,8 @@ CollectorBlock::CollectorBlock(int s)
: size(s),
filled(0),
prev(0L),
- next(0L)
+ next(0L),
+ flags(new char[s])
{
mem = new ValueImp*[size];
}
@@ -58,6 +60,7 @@ CollectorBlock::CollectorBlock(int s)
CollectorBlock::~CollectorBlock()
{
delete [] mem;
+ delete [] flags;
mem = 0L;
}
@@ -108,7 +111,7 @@ void* Collector::allocate(size_t s)
// VI_CREATED and VI_GCALLOWED being unset ensure that value
// is protected from GC before any constructors are run
- static_cast<ValueImp*>(m)->_flags = 0;
+ //static_cast<ValueImp*>(m)->_flags = 0;
if (!root) {
root = new CollectorBlock(BlockSize);
@@ -134,7 +137,9 @@ void* Collector::allocate(size_t s)
}
currentBlock = block;
// fill free spot in the block
- *(block->mem + block->filled) = m;
+ block->mem[block->filled] = m;
+ block->flags[block->filled] = 0;
+ m->_flags = block->flags + block->filled;
filled++;
block->filled++;
@@ -161,7 +166,7 @@ bool Collector::collect()
ValueImp **r = block->mem;
assert(r);
for (int i = 0; i < block->filled; i++, r++)
- (*r)->_flags &= ~ValueImp::VI_MARKED;
+ block->flags[i] &= ~ValueImp::VI_MARKED;
block = block->next;
}
@@ -185,8 +190,8 @@ bool Collector::collect()
{
ValueImp *imp = (*r);
// Check for created=true, marked=false and (gcallowed=false or refcount>0)
- if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
- ( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) {
+ if ((block->flags[i] & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
+ ( (block->flags[i] & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) {
//fprintf( stderr, "Collector marking imp=%p\n",(void*)imp);
imp->mark();
}
@@ -202,7 +207,7 @@ bool Collector::collect()
for (int i = 0; i < block->filled; i++, r++) {
ValueImp *imp = (*r);
// Can delete if marked==false
- if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED ) {
+ if ((block->flags[i] & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED ) {
// emulate destructing part of 'operator delete()'
//fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
imp->~ValueImp();
@@ -220,7 +225,7 @@ bool Collector::collect()
int del = 0;
for (int i = 0; i < block->filled; i++, r++) {
ValueImp *imp = (*r);
- if ((imp->_flags & ValueImp::VI_DESTRUCTED) != 0) {
+ if ((block->flags[i] & ValueImp::VI_DESTRUCTED) != 0) {
free(imp);
del++;
if (!firstfreeset) {
@@ -228,7 +233,9 @@ bool Collector::collect()
freespot = r - block->mem;
}
} else if (firstfreeset) {
- *(block->mem + freespot) = imp;
+ block->mem[freespot] = imp;
+ imp->_flags = block->flags + freespot;
+ block->flags[freespot] = block->flags[i];
freespot++;
}
}
More information about the kfm-devel
mailing list