Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

App runs slowly when BDS IDE not running

Status
Not open for further replies.

Duoas

Programmer
Apr 15, 2008
95
US
Hello all. I'm new here. I've googled and searched this forum for a while now and can't find -anything- that describes my problem.

I'm writing a simple little app that repaints its entire window (about 15% of the screen real-estate) on each FormPaint event. Using Delphi 2006.

When BDS is running the application runs about five times faster than when BDS is not running. Even when executing directly from the command line either way.

Hence, I get nice, smooth animation and input response when BDS is quietly running in its process. But as soon as I shut it down (and restart my application) my application behaves very sluggishly.

Does anyone know what is causing this and where I can look to fix it?

Thank you kindly.
 
Eh, I've learned new information. My FormPaint uses tCanvas.stretchDraw about ten times. This appears to be the bottleneck (which I will remove).

Still, I wonder why it should work so quickly when the IDE is running and so slowly otherwise?
 
Last bump.

If anyone knows what the BDS IDE does that makes things faster I'd like to know (so I can do it too).

With IDE running (even in a _separate_ process): FPS = 25
Running my application without IDE active: FPS = 11

That's a significant performance hit!
 
show us some code, maybe we can help

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Here it is, as simply as I can get it.

Uses the Graphics32 library.

Code:
type
  // Basically, an image region is used as a collision box against the
  // mouse pointer, so that when the images are dragged I know which one is
  // under the mouse.
  tImageRegion = record
    is_used:     boolean;
    image_index: integer;
    area:        tRect
    end;

  tMainForm = class( tForm )
      ...
    private

      f_image_regions: array of tImageRegion;
        // The array is sized to a couple more than the maximum that can be
        // used. However, the number that are actually used at any given time
        // will change with how close the scroll grip is to the ends of the
        // scrollbar.

      f_image_list: tImageList;
        // NOT the VCL type. This is my own type that manages the cached 
        // thumbnails and information about how to display the image and
        // where to find it on disk.
        //
        // It is essentially a wrapper around an array of tImageListDatum
        // objects.

      ...
    end;

Code:
type
  tImageListDatum = class
    public
      title:        string;    // The name of the image to present to the user
      name:         string;    // The relative path name of the image
      bitmap:       tBitmap32; // The image/thumbnail bitmap
      tinymap:      tBitmap32; // The cached small version of the thumbnail
      tagStyle:     integer;   // One of the TAG_STYLE_X constants (defined in uMainForm)
      absolutePath: string;    // The full path of the image as found on disk
    ...
    end;

Code:
//----------------------------------------------------------------------------
// Displays the selectable thumbnail images on the form.
// The form itself is displayed in one of the given modes:
//   fdmTransparent - uses the tForm.transparentColor (slowest)
//   fdmClear       - looks the same as fdmTransparent, but by cheating
//   fdmBlend       - similar, but with darkened background
//   fdmSolid       - a plain black background
// Efficiency is paramount here.
//
// The form background is entirely repainted.
// The cached thumbnails are painted.
// The cached title image is painted.
// The proc exits and the other controls on the form repaint themselves.
//
procedure tMainForm.FormPaint( sender: tObject );
  var i: integer;
  begin
  inc( DebugData.paint_count );

  // Update the background
  case Options.FormDisplayMode of

    fdmSolid:
      with canvas do begin
        brush.color := clBlack;
        brush.style := bsSolid;
        fillRect( rect( 0, 0, clientWidth, clientHeight ) );

        brush.color := clGray;
        fillRect( rect( 0,               0, clientWidth,            1 ) );
        fillRect( rect( 0, clientHeight -1, clientWidth, clientHeight ) )
        end;

    fdmBlend,
    fdmClear:
      f_background.drawTo( canvas.handle, 0, 0 )

    end;

  // Draw the thumbnail images
  PaintThumbnails( true );

  // Draw the name of the current image
  // or
  // Draw the name of the image under the mouse pointer
  i := GetImageRegion( screenToClient( mouse.cursorPos ), true );
  if f_image_regions[ i ].is_used
    then DrawImageTitle( f_image_regions[ i ].image_index )
    else DrawImageTitle( f_index_of_current_image )
  end;

Code:
//----------------------------------------------------------------------------
// This is the guts of the FormPaint procedure.
//
// It calculates and optionally draws the visible thumbnail images in their
// proper positions.
//
// Various class variables are updated:
//   f_index_of_current_image
//   f_index_of_image_on_right
//   f_index_of_image_on_left
//
//   f_image_regions
//
procedure tMainForm.PaintThumbnails( isPaint: boolean );
  var
    percent:        extended;
    offset:         extended;
    image_index:    integer;
    image_offset:   extended;
    x, xc, w, h, i: integer;    // x, x center, width, height, index
    dest:           tBitmap32;
    cri:            integer;    // click region index

  //..........................................................................
  procedure inner_loop_paint;
    begin
    with f_image_list[ i ] do

      if offset < 0.300001
        then begin
             if tinymap = nil then begin
               tinymap := tBitmap32.create;
               tinymap.setSize( w, h );
               StretchTransfer(
                 tinymap,
                 tinymap.clipRect,
                 tinymap.clipRect,
                 bitmap,
                 bitmap.boundsRect,
                 f_resampler,
                 dmOpaque
                 )
               end;
             tinymap.drawTo(
               canvas.handle,
               f_image_regions[ cri ].area.left,
               f_image_regions[ cri ].area.top
               )
             end
        else begin
             dest := tBitmap32.create;
             try
               dest.setSize( w, h );
               StretchTransfer(
                 dest,
                 dest.clipRect,
                 dest.clipRect,
                 bitmap,
                 bitmap.boundsRect,
                 f_resampler,
                 dmOpaque
                 );
               dest.drawTo(
                 canvas.handle,
                 f_image_regions[ cri ].area.left,
                 f_image_regions[ cri ].area.top
                 )
             finally dest.free end
             end
    end;

  //..........................................................................
  begin
  // Calculate the current percentage across the scrollbar and images
  percent := scroll_grip_position;

  offset := (f_image_list.count -1) *percent;

  image_index  := round( offset );
  image_offset := (frac( offset +0.5 ) -0.5);  // -->  -0.5  ..  +0.5


  // Draw the active image full-size . . . . . . . . . . . . . . . . . . . . .
  xc := img_scroll_grip.left +(img_scroll_grip.width div 2)
       -round( IMAGE_WIDTH_MAXIMUM *image_offset )
       -(IMAGE_WIDTH_MAXIMUM div 2);

  f_index_of_current_image := image_index;

  if f_image_list.count < f_index_of_current_image then exit;

  with f_image_regions[ 0 ] do begin
    is_used     := TRUE;
    image_index := f_index_of_current_image;
    area        := rect(
                     xc,
                     IMAGE_BOTTOM_EDGE_OFFSET -IMAGE_HEIGHT_MAXIMUM,
                     xc                       +IMAGE_WIDTH_MAXIMUM +DISTANCE_BETWEEN_IMAGES +1,
                     IMAGE_BOTTOM_EDGE_OFFSET                                               +1
                     )
    end;
  cri := 1;

  if isPaint then
    with f_image_list[ f_index_of_current_image ] do
      bitmap.drawTo(
        canvas.handle,
        xc,
        IMAGE_BOTTOM_EDGE_OFFSET -IMAGE_HEIGHT_MAXIMUM
        );


  // Draw all images to the right  . . . . . . . . . . . . . . . . . . . . . .
  f_index_of_image_on_right := image_index;
  i      := image_index +1;
  x      := xc +IMAGE_WIDTH_MAXIMUM +DISTANCE_BETWEEN_IMAGES;
  offset := ((image_offset +0.5) *0.4) +0.6;
  while x < self.width do begin
    if i >= f_image_list.count then break;
    f_index_of_image_on_right := i;
    w := round( IMAGE_WIDTH_MAXIMUM  *offset );
    h := round( IMAGE_HEIGHT_MAXIMUM *offset );

    with f_image_regions[ cri ] do begin
      is_used     := true;
      image_index := i;
      area.left   := x;
      area.right  := x +w +DISTANCE_BETWEEN_IMAGES                     +1;
      area.bottom := IMAGE_BOTTOM_EDGE_OFFSET -30 +round( offset *30 ) +1;
      area.top    := area.bottom -h
      end;

    if isPaint then inner_loop_paint;

    inc( cri );
    inc( i );
    inc( x, w +DISTANCE_BETWEEN_IMAGES );
    offset := max( offset *0.6, 0.3 )
    end;


  // Draw all images to the left . . . . . . . . . . . . . . . . . . . . . . .
  f_index_of_image_on_left := image_index;
  i      := image_index -1;
  x      := xc -DISTANCE_BETWEEN_IMAGES;
  offset := ((1.0 -(image_offset +0.5)) *0.4) +0.6;
  while x > 0 do begin
    if i < 0 then break;
    f_index_of_image_on_left := i;
    w := round( IMAGE_WIDTH_MAXIMUM  *offset );
    h := round( IMAGE_HEIGHT_MAXIMUM *offset );

    with f_image_regions[ cri ] do begin
      is_used     := true;
      image_index := i;
      area.left   := x -w;
      area.right  := x +DISTANCE_BETWEEN_IMAGES                        +1;
      area.bottom := IMAGE_BOTTOM_EDGE_OFFSET -30 +round( offset *30 ) +1;
      area.top    := area.bottom -h
      end;

    if isPaint then inner_loop_paint;

    inc( cri );
    dec( i );
    dec( x, w +DISTANCE_BETWEEN_IMAGES );
    offset := max( offset *0.6, 0.3 )
    end;

  // End of image regions
  f_number_of_visible_images := cri;  //mtg del
  with f_image_regions[ cri ] do begin
    is_used     := false;
    image_index := i +1
    end
  end;

Some of the floating-point calculations I plan to offload from out of the PaintThumbnails routine, but ATM it isn't a huge factor.


The problem is, again, that this is the identical code that I run for each test.
When BDE is running, it gets about 25 FPS.
When BDE is not running, it gets less than half that.

If I haven't changed the executable between tests, surely it is something that BDE is doing?

Thanks for your time... :)
 
Ack! Sorry for the double-post! I forgot to post a thumbnail.

(Sorry, my sys admin changed my ISP from Comcast to Verizon and hasn't given me any webspace yet...)
 
With versions D7 and before, there is a Project Option under Packages, to "Build with runtime packages".

When unchecked, all bpl's (component packages) are built into the application.

Checked, and they're not, requiring external calls to load/unload, depending on memory avail, cache sizes, etc.

Sounds backward, I know. That just may be your issue. Not sure but worth a try. Please let us know...

Your production compile should also have debug and I/O checking turned off for optimum performance.

Roo
Delphi Rules!
 
Hey, thanks for the input.

I tried those already, to no effect... alas.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top