Andreas Ekstrand wrote:

I have only measured the timing in debug mode, and my feeling of running in 
optimized release mode is that it's even faster with the old implementation, 
that the difference between the old and new implementation feels larger there. 
I guess it's different how much optimization that can be done with the two 
implementations.

With Fl_Scroll::remove in Debug mode, clear took about 2400ms.
With the old (1.1) or new (1.3) implementation?

With the new 1.3 implementation. Actually, when I refer to the "old 
implementation", I mean revision 6656 of the 1.3 branch, which is what we used 
previously. Excuse me for any unclear statements that I have made.

Your suggested method of using Fl_Scroll::clear is unfortunately too slow, 
about 2500ms. I also thought it would be faster because of the reversed removal 
order, but for some reason it isn't.

I really appreciate that you take the time to look into this issue. But since 
we can't see a possible quick solution for this, I have to consider the option 
of moving back to an older 1.3 revision or even 1.2 (originally chosen for the 
32 bit widget coordinates). It would hurt going back there, but this 
performance drop is too big to cope with, I'm afraid...

Please wait a moment!

I'm just testing a new *optimized* implementation :-)

Results with 40,000 children (Fl_Buttons) in Fl_Scroll:

old implementation:
 - Fl_Group::clear()  about 1.9 - 2.0 sec.
 - Fl_Scroll::clear() about 1.3 sec.

new implementation:   about 0.03 - 0.05 sec !

This new implementation will also be used in Fl_Scroll::clear()
without a significant slowdown effect.

I guess you'll like it. ;-)

Would you like to test it yourself? I'll append the two methods
to replace in this message. They should replace the complete
old methods.

*** without any guarantees and promises ***

I also appended scroll.cxx (my test program). Tested with
Windows only.

Comments and test results will be appreciated !

Albrecht

----- Fl_Group::clear() -----

/* Implementation note:
  This is optimized and does not remove children _during_ the loop.
  However, deleting one child may also delete other children in the
  group because a child widget can destroy other children in the same
  group in its destructor or simply remove them from the parent group.
  Because of this we must walk forwards through the array of children.
  The allocated array_ of children is free'd after the loop.
*/
void Fl_Group::clear() {
  savedfocus_ = 0;
  resizable_ = this;
  init_sizes();
  // okay, now it is safe to destroy the children:
  int i;
  for (i=0; i<children_; i++) {      // delete all children
    Fl_Widget* o = child(i);    // get child widget
    if (o->parent()==this) { // should always be true
      o->parent_ = 0;                // reset child's parent
      delete o;                 // delete it
    }
  }
  // now free the array_ of children (if any)
  if (children_ > 1) {
    free((void*)array_);
  }
  array_ = 0;
  children_ = 0;
}

----- Fl_Scroll::clear() -----

void Fl_Scroll::clear() {
  remove(hscrollbar);
  remove(scrollbar);
  Fl_Group::clear();
  add(hscrollbar);
  add(scrollbar);
}
//
// modified Fl_Scroll test program for the Fast Light Tool Kit (FLTK).
//

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/Fl_Button.H>

#include <time.h>
#include <sys/timeb.h>
#include <stdio.h>

#include <string.h>
#include <stdio.h>

static char *ctime ()
{
  static char tbuf[40];
  struct timeb  ctime;
  struct tm     *lt;
  ftime (&ctime);
  lt = localtime (&ctime.time);
  sprintf (tbuf,"%2.2d:%2.2d:%2.2d.%2.2d",
                lt->tm_hour,
                lt->tm_min,
                lt->tm_sec,
                ctime.millitm/10);
  return tbuf;
}

Fl_Scroll* thescroll = 0;
Fl_Scrollbar* hsb = 0;
Fl_Scrollbar* vsb = 0;

void clear_cb(Fl_Widget*, void* v) {

#ifdef CLEAR_READQUEUE
  int i;
  for (i=0; i<99; i++)
    if (!Fl::readqueue()) break;
  printf ("Fl::readqueue() - flushed %d entries\n",i);
#endif
  printf ("clear_cb: %s - started,  
children=%5d\n",ctime(),thescroll->children());

#define USE_GROUP_CLEAR
#ifdef USE_GROUP_CLEAR
  printf ("using Fl_Group::clear()\n");
  thescroll->remove(hsb);
  thescroll->remove(vsb);
  thescroll->Fl_Group::clear();
  thescroll->add(hsb);
  thescroll->add(vsb);
#else
  printf ("using Fl_Scroll::clear()\n");
  thescroll->clear();
#endif
  printf ("clear_cb: %s - finished, 
children=%5d\n",ctime(),thescroll->children());
  thescroll->redraw();
}

int main(int argc, char** argv) {

  setvbuf (stdout,NULL,_IONBF,0);       // stdout unbuffered
  Fl_Window window(600,400);
  Fl_Scroll scroll(0,0,600,300);

  int n = 0;
  for (int y=0; y<400; y++) for (int x=0; x<100; x++) {
    char buf[20]; sprintf(buf,"%d",n++);
    Fl_Button* b = new Fl_Button(x*60,y*20,60,20);
    b->copy_label(buf);
    b->color(n%128);
    b->labelcolor(FL_WHITE);
  }
  scroll.end();
  window.resizable(scroll);

  thescroll = &scroll;
  hsb = &thescroll->hscrollbar;
  vsb = &thescroll->scrollbar;
  
  Fl_Button *clear = new Fl_Button (20,320,60,20,"clear");
  clear->callback(clear_cb);

  window.end();
  window.show(argc,argv);
  return Fl::run();
}
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to