Albrecht Schlosser wrote:

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 just committed subversion release 7038 with the optimized
version of both Fl_Group::clear() and Fl_Scroll::clear().

FWIW: I'll also append my last version of the test/demo program
that shows the measured time for creating and deleting up to
100,000 buttons in/from an Fl_Scroll.

Figures: Windows XP, Pentium 4 (2.41 GHz), old vs. optimized:

100,000 buttons: 12.235 vs. 0.109 seconds.
 50,000 buttons:  3.047 vs. 0.047 seconds.
 10,000 buttons:  0.125 vs. 0.016 seconds.

Albrecht
//
// modified Fl_Scroll test program for the Fast Light Tool Kit (FLTK).
// version 2: dynamic loading of widgets
//

#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 <FL/Fl_Check_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_Output.H>
#include <FL/fl_ask.h>

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

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

static char *ctime (double *secs)
{
  static char tbuf[40];
  struct timeb  ctime;
  struct tm     *lt;
  ftime (&ctime);
  lt = localtime (&ctime.time);
  sprintf (tbuf,"%2.2d:%2.2d:%2.2d.%3.3d",
                lt->tm_hour,
                lt->tm_min,
                lt->tm_sec,
                ctime.millitm);
  if (secs) { // return seconds and milliseconds
    *secs = (double)lt->tm_sec + ((double)ctime.millitm)/1000.0;
  }
  return tbuf;
}

Fl_Scroll* thescroll = 0;
Fl_Scrollbar* hsb = 0;
Fl_Scrollbar* vsb = 0;
Fl_Value_Slider *numb = 0;
Fl_Check_Button *cq = 0;
Fl_Output *dtime = 0;

double start, end, delta;

static void set_time() {
  char buf[30];
  delta = end - start;
  if (delta<0) delta += 60.0;
  sprintf (buf,"%5.3f sec.",delta);
  dtime->value(buf);
  printf ("--> delta time = %5.3f sec.\n",delta);
}

void reset_cb(Fl_Widget*, void* v) {

  printf ("reset_cb: %s - started,  
children=%6d\n",ctime(&start),thescroll->children());

  int nw = (int)numb->value();
  if (nw <1000 || nw > 100000) nw = 20000;
  if (thescroll->children() > 2) {
    fl_alert("You must clear the scroll group first");
    return;
  }
  Fl_Group *curr = Fl_Group::current();
  thescroll->begin();
  int n = 0;
  for (int y=0; y<(nw+99)/100; 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);
    if (n > nw) break;
  }
  Fl_Group::current(curr);

  printf ("reset_cb: %s - finished, 
children=%6d\n",ctime(&end),thescroll->children());
  set_time();
}

void clear_cb(Fl_Widget*, void* v) {

  int use_group = (int)v;

  if (cq->value()) {
    int i;
    for (i=0; i<99; i++)
      if (!Fl::readqueue()) break;
    printf ("Fl::readqueue() - flushed %d entries\n",i);
  }

  if (use_group) {
    printf ("using Fl_Group::clear()\n");
  } else {
    printf ("using Fl_Scroll::clear()\n");
  }

  printf ("clear_cb: %s - started,  
children=%6d\n",ctime(&start),thescroll->children());

  if (use_group) {
    thescroll->remove(hsb);
    thescroll->remove(vsb);
    thescroll->Fl_Group::clear();
    thescroll->add(hsb);
    thescroll->add(vsb);
  } else {
    thescroll->clear();
  }
  printf ("clear_cb: %s - finished, 
children=%6d\n",ctime(&end),thescroll->children());
  set_time();
  thescroll->redraw();
}

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

  setvbuf (stdout,NULL,_IONBF,0);       // stdout unbuffered
  Fl_Window window(600,420);
  Fl_Scroll scroll(0,0,600,300);
  thescroll = &scroll;                  // save global vars
  hsb = &thescroll->hscrollbar;
  vsb = &thescroll->scrollbar;
  scroll.end();
  scroll.type(Fl_Scroll::BOTH);
  window.resizable(scroll);

  Fl_Button *clear0 = new Fl_Button (20,320,120,20,"Fl_Scroll::clear");
  clear0->callback(clear_cb,(void*)0);

  Fl_Button *clear1 = new Fl_Button (20,350,120,20,"Fl_Group::clear");
  clear1->callback(clear_cb,(void*)1);

  cq = new Fl_Check_Button (20,380,160,20,"clear Fl::readqueue");
  cq->value(0);

  dtime = new Fl_Output (200,350,80,20,"time:");
  dtime->value("");

  numb = new Fl_Value_Slider (380,320,200,25,"buttons:");
  numb->minimum(1000);
  numb->maximum(100000);
  numb->step(100);
  numb->labelsize(16);
  numb->align(FL_ALIGN_LEFT);
  numb->type(FL_HORIZONTAL);
  numb->value(10000);

  Fl_Button *res = new Fl_Button (380,350,200,20,"create buttons");
  res->callback(reset_cb,(void*)0);

  window.end();

  // reset_cb(thescroll,(void*)0);              // add the buttons

  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