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