JS speed - Konq vs. Mozilla
Koos Vriezen
koos.vriezen at xs4all.nl
Wed Sep 4 18:46:20 BST 2002
On Wed, 4 Sep 2002, Koos Vriezen wrote:
> Attached a little bigger patch that makes KJS::Collector::allocate a
> bit faster and less memory hungry.
> Now, it removes this loop
> while (*r)
> r++;
> by remembering where it stopped the last time and swapping all free slots
> at the end of a block.
Hmmm, now that all free slots are at the end of the block, the 'firstfree'
value of a block is always the same as 'filled'. So I stripped that out.
There is also no need for a 'memset' call in the CollectorBlock
constructor and setting '*r = 0L' in the collector anymore (because we
can iterate from 0 to filled). This also eliminates the need for
'if (imp)' in the collector.
I think this will be my final patch for the Collector for now, because
there is only 5-7% speed to gain here (compared to a allocator that just
returns 'malloc(size)').
Real speed gain should be found elsewhere. A gprof output for the tested
script, posted earlier in this thread, shows that KJS::Value::~Value() is
called 299335 and KJS::Value::imp() 356709 times!
Regards,
Koos
-------------- next part --------------
Index: collector.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/collector.cpp,v
retrieving revision 1.33
diff -u -3 -p -r1.33 collector.cpp
--- collector.cpp 2002/08/22 13:37:51 1.33
+++ collector.cpp 2002/09/04 17:44:11
@@ -53,7 +53,6 @@ CollectorBlock::CollectorBlock(int s)
next(0L)
{
mem = new ValueImp*[size];
- memset(mem, 0, size * sizeof(ValueImp*));
}
CollectorBlock::~CollectorBlock()
@@ -134,11 +133,8 @@ void* Collector::allocate(size_t s)
block = tmp;
}
currentBlock = block;
- // look for a free spot in the block
- ValueImp **r = block->mem;
- while (*r)
- r++;
- *r = m;
+ // fill free spot in the block
+ *(block->mem + block->filled) = m;
filled++;
block->filled++;
@@ -164,10 +160,8 @@ bool Collector::collect()
while (block) {
ValueImp **r = block->mem;
assert(r);
- for (int i = 0; i < block->size; i++, r++)
- if (*r) {
- (*r)->_flags &= ~ValueImp::VI_MARKED;
- }
+ for (int i = 0; i < block->filled; i++, r++)
+ (*r)->_flags &= ~ValueImp::VI_MARKED;
block = block->next;
}
@@ -187,12 +181,11 @@ bool Collector::collect()
while (block) {
ValueImp **r = block->mem;
assert(r);
- for (int i = 0; i < block->size; i++, r++)
+ for (int i = 0; i < block->filled; i++, r++)
{
ValueImp *imp = (*r);
// Check for created=true, marked=false and (gcallowed=false or refcount>0)
- if (imp &&
- (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
+ if ((imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) {
//fprintf( stderr, "Collector marking imp=%p\n",(void*)imp);
imp->mark();
@@ -206,11 +199,10 @@ bool Collector::collect()
block = root;
while (block) {
ValueImp **r = block->mem;
- for (int i = 0; i < block->size; i++, r++) {
+ for (int i = 0; i < block->filled; i++, r++) {
ValueImp *imp = (*r);
// Can delete if marked==false
- if (imp &&
- (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED ) {
+ if ((imp->_flags & (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();
@@ -223,17 +215,26 @@ bool Collector::collect()
block = root;
while (block) {
ValueImp **r = block->mem;
+ int freespot = block->filled;
+ bool firstfreeset = false;
int del = 0;
- for (int i = 0; i < block->size; i++, r++) {
+ for (int i = 0; i < block->filled; i++, r++) {
ValueImp *imp = (*r);
- if (imp && (imp->_flags & ValueImp::VI_DESTRUCTED) != 0) {
- free(imp);
- *r = 0L;
+ if ((imp->_flags & ValueImp::VI_DESTRUCTED) != 0) {
+ free(imp);
del++;
+ if (!firstfreeset) {
+ firstfreeset = true;
+ freespot = r - block->mem;
+ }
+ } else if (firstfreeset) {
+ *(block->mem + freespot) = imp;
+ freespot++;
}
}
filled -= del;
block->filled -= del;
+ assert(freespot == block->filled);
block = block->next;
if (del)
deleted = true;
@@ -241,6 +242,8 @@ bool Collector::collect()
// delete the empty containers
block = root;
+ currentBlock = 0L;
+ CollectorBlock *last = root;
while (block) {
CollectorBlock *next = block->next;
if (block->filled == 0) {
@@ -250,13 +253,18 @@ bool Collector::collect()
root = next;
if (next)
next->prev = block->prev;
- if (block == currentBlock) // we don't want a dangling pointer
- currentBlock = 0L;
assert(block != root);
delete block;
+ } else if (!currentBlock) {
+ if (block->filled < block->size)
+ currentBlock = block;
+ else
+ last = block;
}
block = next;
}
+ if (!currentBlock)
+ currentBlock = last;
#if 0
// This is useful to track down memory leaks
static int s_count = 0;
More information about the kfm-devel
mailing list