Jump to content

How to optimize uniDBGrid Rendering


irigsoft

Recommended Posts

Hello,

I don't use mobile components, but I work on mobile devices.

I use unigui Professional 1537, (but this problem also exists in version 1526).

my problem is:

1. I create the columns in DBgrid at runtime, each reload of the query to DBGrid recreates the columns.

2. On a mobile device, to show the result (running AdoQuery + creating all columns (visible and invisible) + creating a summary), I use a device with 2 GB of RAM, Android and mobile Chrome

3. To optimize rendering, I use DisableControls, SuspendLayouts, SuspendColumnsChanged when creating columns and running Query,

4. I limited the page size to 25, DBGrid is Paged and the result in Query is limited to the page size in the results.

5. In grid I have column with image, and other column with action button. Image size is 32 from ImageList. When image is missing work better, maybe image optimization I need ?

5. The server has 3GHz, 4GB RAM, Win10, SSD, Windows Defender is Active

6. My application in production is protected by Virtualization and Mutation. When I use it none protected speed is with 1 second faster.

7. Unigui Application is StandAlone

8. I can't use javascript XTemplates

The time to display all lines is 2-3 seconds, I will ask for assistance in speeding up this visualization with some javascript commands.
Thanks in advance !

Link to comment
Share on other sites

4 hours ago, irigsoft said:

Hello,

I don't use mobile components, but I work on mobile devices.

I use unigui Professional 1537, (but this problem also exists in version 1526).

my problem is:

1. I create the columns in DBgrid at runtime, each reload of the query to DBGrid recreates the columns.

2. On a mobile device, to show the result (running AdoQuery + creating all columns (visible and invisible) + creating a summary), I use a device with 2 GB of RAM, Android and mobile Chrome

3. To optimize rendering, I use DisableControls, SuspendLayouts when creating columns and running Query,

4. I limited the page size to 25, DBGrid is Paged and the result in Query is limited to the page size in the results.

5. In grid I have column with image, and other column with action button. Image size is 32 from ImageList. When image is missing work better, maybe image optimization I need ?

5. The server has 3GHz, 4GB RAM, Win10, SSD, Windows Defender is Active

6. My application in production is protected by Virtualization and Mutation. When I use it none protected speed is with 1 second faster.

7. Unigui Application is StandAlone

8. I can't use javascript XTemplates

The time to display all lines is 2-3 seconds, I will ask for assistance in speeding up this visualization with some javascript commands.
Thanks in advance !

Hello

Are you using OnFieldImage event or OnFieldImageURL event?

Link to comment
Share on other sites

28 minutes ago, Hayri ASLAN said:

Hello

Are you using OnFieldImage event or OnFieldImageURL event?

no, but I have my own OnDrawColumnCell, and OnCellClick

If I "comment" on everything in OnDrawColumnCell, nothing changes

I use DBGrid.ScreenMask.Enabled := True !

Link to comment
Share on other sites

I make this steps, and found something strange:

1. I execute some request in dbgrid

2. close the request, clear sql.text

3. change sql.text and run again

, after point 3 dbgrid first shows the old result and then shows the new result.

The problem I see is that after point 2 dbgrid does not refresh the result, it just shows the old result. it may take time to refresh ?

Link to comment
Share on other sites

13 minutes ago, irigsoft said:

I make this steps, and found something strange:

1. I execute some request in dbgrid

2. close the request, clear sql.text

3. change sql.text and run again

, after point 3 dbgrid first shows the old result and then shows the new result.

Hello,

How can we reproduce this behavior?

Link to comment
Share on other sites

On 6/16/2022 at 8:18 AM, Sherzod said:

Hello,

How can we reproduce this behavior?

Hello, I am sorry I can't create test example, but I will explain my configuration:

1. I use MS SQL 2008 as Database

2. use TAdoQuery, and uniDBGrid

3. before execute Query (To ignore refreshing i set DBGrid.Visible := False) I clear sql.Text, clear Columns, create new colums (from Stringlist with settings),

4. create action columns with Columns.Insert (0);

here is code for point 3 (GetFunc - CREATEDBGRDIDTAB..... is take 500ms)

1. Clear Close AdoQuery

if TuniDBGrid (SelDBGrid).DataSource.DataSet <> nil then begin
       TuniDBGrid (SelDBGrid).DataSource.DataSet.Close;
       //TuniDBGrid (SelDBGrid).
      // UniSession.JSCode(SelDBGrid.JSName + '.view.refresh();');
  end;

2. Close SQl and Clear columns

TAdoQuery (SelDBGrid.DataSource.DataSet).Close;
TuniDBGrid (SelDBGrid).SuspendColumnsChanged := True;
UniSession.JSCode(SelDBGrid.JSName + '.store.suspendEvents();');
TuniDBGrid (SelDBGrid).Columns.Clear;

IF TuniDBGrid (SelDBGrid).Columns <> nil then begin
      TuniDBGrid (SelDBGrid).Columns.BeginUpdate;
      TuniDBGrid (SelDBGrid).SuspendColumnsChanged := True;
      if TuniDBGrid (SelDBGrid).DataSource.DataSet <> nil then begin
          TRY
          //TuniDBGrid (SelDBGrid).DataSource.DataSet.Close;
          //TuniDBGrid (SelDBGrid).DataSource.DataSet.DisableControls;
          //if CreateGrid then begin
          TempQuery := TAdoQuery (TuniDBGrid (SelDBGrid).DataSource.DataSet);
          TempQuery.Close;
          TempQuery.SQL.Clear;
          TuniDBGrid (SelDBGrid).DataSource.DataSet := nil;
          for I := TuniDBGrid (SelDBGrid).Columns.Count - 1 downto 0 do begin
              TuniDBGrid (SelDBGrid).Columns.Items[I].Destroy;
          end;
          TuniDBGrid (SelDBGrid).Columns.Clear;
          EXCEPT

          END;
          //UniSession.JSCode(SelDBGrid.JSName + '.view.refresh();');

          TuniDBGrid (SelDBGrid).DataSource.DataSet := TempQuery;
          TempQuery := nil;

          //TuniDBGrid (SelDBGrid).DataSource.DataSet.EnableControls;
      end;
      TuniDBGrid (SelDBGrid).SuspendColumnsChanged := False;
      TuniDBGrid (SelDBGrid).Columns.EndUpdate;
    end;

3. create new columns

    //TuniDBGrid (SelDBGrid).SuspendColumnsChanged := True;
    TuniDBGrid (SelDBGrid).Columns.BeginUpdate;
    for I := 0 to FieldsList.Count - 1 do begin
      TRY
          FieldsData.DelimitedText := FieldsList.ValueFromIndex [I];

          //SelDBGrid.Columns.Add;
          MyColumn := TuniDBGrid (SelDBGrid).Columns.Add;
          MyColumn.Font.Size := uniMainModule.ControlsFontSize;
          MyColumn.Title.Font.Size := uniMainModule.ControlsFontSize;
          MyColumn.Title.Alignment := taCenter;
          MyColumn.Title.Caption := FieldsData [0];
          MyColumn.Sortable := True;
          MyColumn.ReadOnly := True;
          MyColumn.ShowSummary := True;
          MyColumn.Width := 0;
          MyColumn.Flex := 0;
          MyColumn.ShowToolTipAlways := False;
          //MyColumn.CheckBoxField.Enabled := False;
          //MyColumn.Locked := True;

          //MyColumn.DisplayMemo
          IF FieldsData.Count > 1 then begin
              if StrToInt (FieldsData [1]) > -1 then begin
                  MyColumn.Width := StrToInt (FieldsData [1]);
              end
              else begin
                  MyColumn.Visible := False;
                  //SelDBGrid.JSInterface.JSCall('hide', [SelDBGrid.Columns[MyColumn.Index].Visible], SelDBGrid.Columns[MyColumn.Index].JSColumn);
                  SelDBGrid.JSInterface.JSCall('show', [MyColumn.Visible], SelDBGrid.Columns[MyColumn.Index].JSColumn);
                  //MyColumn.Menu.MenuEnabled := False;
                  MyColumn.Menu.ColumnHideable := False;
                  MyColumn.Width := StrToInt (FieldsData [1]);
                  //SelDBGrid.JSInterface.JSCall ('setVisible', [false], SelDBGrid.Columns [MyColumn.Index].JSColumn);
              end;
          end;
          MyColumn.FieldName := TRIM (FieldsList.Names [I]);
          //MyColumn.Hint := FieldsData [2];

          //MyColumn.Wrap := True;
          //SelDBGrid.Columns.Items [SelDBGrid.Columns.Count - 1].Assign (MyColumn);
      EXCEPT
         on e:exception do begin
         end;
      END;
      TuniDBGrid (SelDBGrid).Columns.EndUpdate;
      TuniDBGrid (SelDBGrid).SuspendColumnsChanged := False;

    end;//for I

4. Add ActionColumn
 

    ActionColumnList := TStringList.Create;
    ActionColumnList.StrictDelimiter := True;
    ActionColumnList.Delimiter := ',';
    ActionColumnList.DelimitedText := TRIM (sActionColumnLeft);
    if ActionColumnList.Count > 0 then begin
          ImagesExist := False;
          if SelDBGrid.Images <> nil then begin
             ImagesExist := True;
             If FindComponentEx (SelDBGrid.Images.Name) <> nil then begin
                 GridImageList := TuniImageLIst (SelDBGrid.Images);
                 TuniImageLIst (SelDBGrid.Images).Clear;
                 TuniImageLIst (SelDBGrid.Images).Height := 32;
                 TuniImageLIst (SelDBGrid.Images).Width := 32;
             end;
          end
          else begin
            TRY
              GridImageList := TuniImageList (FindComponentEx ('ImageList_'+ SelDBGrid.Name));

              if (not Assigned (GridImageList))
              Or (GridImageList = nil)
              then begin
                  GridImageList := TuniImageList.Create (UniSession.FormsList [UniSession.FormsList.Count -1]);//uniMainModule);
                  GridImageList.Name := 'ImageList_'+ SelDBGrid.Name;
                  GridImageList.UseGlobalCache := True;
              end;
              GridImageList.Clear;
              GridImageList.Height := 32;
              GridImageList.Width := 32;

              SelDBGrid.Images := GridImageList;
            EXCEPT
                 on E:Exception do begin
                 end;
            END;

          end;//else
          //MyColumn := SelDBGrid.Columns.Add;//TColumn.Create(SelDBGrid.Columns);
          TuniDBGrid (SelDBGrid).Columns.BeginUpdate;
          for I := ActionColumnList.Count - 1 downto 0 do begin
                sBtn := TuniBitBtn (FindComponentEx (ActionColumnList [I]));
                if Assigned (sBtn) then begin
                    SelDBGrid.Columns.Insert (0);//TColumn.Create(SelDBGrid.Columns);
                    SelDBGrid.Columns [0].Title.Alignment := taCenter;
                    SelDBGrid.Columns [0].Title.Caption := '';
                    //SelDBGrid.Columns [0].Width := GridImageList.Width;
                    //If iActionColumnWidth > 0 then
                    SelDBGrid.Columns [0].Width := iActionColumnWidth;
                    //SelDBGrid.Columns [0].Width := ActionColumnList.Count * SelDBGrid.Columns [0].Width;
                    SelDBGrid.Columns [0].Alignment := taCenter;
                    SelDBGrid.Columns [0].ActionColumn.Create;
                    SelDBGrid.Columns [0].ActionColumn.Enabled := True;
                    Try
                        BtnCol := TuniCustomButtonItem (SelDBGrid.Columns [0].ActionColumn.Buttons.Add);
                        //BtnCol.ScreenMask.Enabled := True;
                        //BtnCol.Width := ROUND (SelDBGrid.Columns [0].Width div ActionColumnList.Count);
                        //BtnCol.ScreenMask.Enabled := True;
                        //sBtn := TuniBitBtn (FindComponentEx (ActionColumnList [I]));
                        //if Assigned (sBtn) then begin
                        //BtnCol.ImageIndex :=
                        SelDBGrid.Columns [0].Title.Caption := TuniControl (sBtn).Caption;
                        //BtnCol.DisplayName := ActionColumnList [I];
                        BtnCol.UI := 'ActionBtn_' + ActionColumnList [I];
                        BtnCol.Hint := sBtn.Hint;
                        BtnCol.Caption := sBtn.Caption;

                        SelDBGrid.Columns [0].ActionColumn.Buttons[BtnCol.ButtonId].Width := iActionColumnWidth;
                        if Assigned (TuniBitBtn (sBtn).Glyph) then begin
                            try
                                msBinImgStream := TMemoryStream.Create;
                                Bmp := TBitMap.Create;
                                TuniBitBtn (sBtn).Glyph.SaveToStream (msBinImgStream);
                                Bmp.Canvas.Lock;
                                msBinImgStream.Position := 0;
                                if msBinImgStream.Size > 0 then begin
                                  Bmp.LoadFromStream(msBinImgStream);
                                  if (msBinImgStream.Size > 0)
                                  AND (msBinImgStream.Size <= TRUNC (20*1024*1024)) then
                                      Bmp := ResizeBmp(Bmp,GridImageList.Height,GridImageList.Width);
                                  //if not ImagesExist then
                                     //GridImageList.Add (Bmp,nil);
                                  BtnCol.ImageIndex := GridImageList.Add (Bmp,nil);
                                  //BtnCol.IconAlign := TuniBitBtn (sBtn).IconAlign;
                                end;
                                Bmp.Canvas.UnLock;

                                msBinImgStream.Size := 0;
                                msBinImgStream.Free;
                                Bmp.Free;
                            except
                                on E:Exception do begin
                                end;
                            end;
                            //BtnCol.ScreenMask.Enabled := True;
                            //SelDBGrid.OnColumnActionClick //Columns [0].ActionColumn.Buttons.ButtonClick := ActionBtnClick;
                            //SelDBGrid.Columns [0].ActionColumn.Buttons.ButtonClick := ActionColumnButtonClick;
                            BtnCol := nil;
                        end;//IF Assigend
                    //end;
                    except
                      //on E:Exception do Showmessage (e.Message);
                    End;
                end;//If
          end;//for
          TuniDBGrid (SelDBGrid).Columns.EndUpdate;

          //SelDBGrid.Images := GridImageList;
    end;//if (ActionColumnList.Count > 0)
    ActionColumnList.Clear;
    ActionColumnList.Free;
 

  TuniDBGrid (SelDBGrid).SuspendColumnsChanged := False;
 

Link to comment
Share on other sites

Hello, I have new information:

I added log into file to my functions to see how time each function is consumed.

Result:

image.png.c60847c8613fde164232865afec8be33.png

This result shows me that the function (execute query, and recreate columns) takes 500 ms to perform, the whole time from the beginning to the end of BtnClick takes 594 ms, but the whole time from clicking to hiding the mask takes 3 seconds, this time (from 3 seconds) is different if I have 5 or 15 lines in the grid (on DBGrid.PageSize= 25), but the time is between 2.5 - 3 seconds

this is the data that is displayed by the DBGrid when the rendering ends (the first column is an action column):

it makes me think that something in rendering slows everything down.

image.png.47c503a0fec1be2cf9d82a6caf792a9b.png

Link to comment
Share on other sites

Hello again.

I have a new question.

Does it matter that in the form I have 20-30 invisible components, for the refresh rate of the grid, let's keep in mind that only the grid is visible?

Components are uniPanels with controls.

Link to comment
Share on other sites

  • 4 weeks later...
On 6/22/2022 at 6:16 PM, irigsoft said:

Does it matter that in the form I have 20-30 invisible components, for the refresh rate of the grid, let's keep in mind that only the grid is visible?

Hello, 

Sorry, can you please explain in more detail? 

Link to comment
Share on other sites

1 hour ago, Sherzod said:

Hello, 

Sorry, can you please explain in more detail? 

I will try.

I have working Form with many components (uniEdits,uniLabel, uniScrollBars, uniPanels, uniBitBtns, uniButtons), all i create it is after user login.

after that I just show or hide it (sometimes with Align := alClient).

In that picture

image.png.47c503a0fec1be2cf9d82a6caf792a9b.png

is visible only DBGrid, but other element (uniBitBtns, uniPanels) are hidden.

I click on uniButton and wait to show Result on DBGrid.

at this picture 

image.png.c60847c8613fde164232865afec8be33.png

i made a procedure that shows me how long it takes from the start to the end of uniBitButton.Click and i see that the execution time is  594ms (that's great) but the result and the mask are displayed 3 seconds after i have clicked the button , but why?

The time to create columns and execute AdoQuery.SQL (via GetFunc - CREATEDBGRDIDTAB.....) is 500ms (that's OK) and I expect some time after that to display and render the dbgrid result, but it's taking longer than expected .

 

Link to comment
Share on other sites

@Sherzod I should say that I have 3 timers in this form (1 second interval) and panels (they are hidden), and these timers refresh the uniPanels.caption. Could this also slow down the unidbgird refresh?

If the button is clicked, then some timers wait for the button events to complete!

 

My test was done on a mobile device with WebView (and Chrome mobile) with 1 GB RAM and Android 6. 

The difference with desktop browsers is 1 second (faster)

Link to comment
Share on other sites

4 hours ago, irigsoft said:

I should say that I have 3 timers in this form (1 second interval) and panels (they are hidden), and these timers refresh the uniPanels.caption. Could this also slow down the unidbgird refresh?

Well, I would not say that this will reduce performance, but why use three timers for "one task"?

Link to comment
Share on other sites

20 minutes ago, Sherzod said:

Well, I would not say that this will reduce performance, but why use three timers for "one task"?

Not of course, each timer has a different task, one refreshes uniPanel.Caption every second, another refreshes a uniDBGrid (hidden) every 30 seconds, another refreshes unibitbtn.Caption (hidden) every 500ms.

Link to comment
Share on other sites

10 minutes ago, irigsoft said:

one refreshes uniPanel.Caption every second

 

10 minutes ago, irigsoft said:

another refreshes unibitbtn.Caption (hidden) every 500ms.

What condition (algorithm) do you use to change the captions? Is it possible to use it only on the client side without loading the server every time?

Link to comment
Share on other sites

1 minute ago, Sherzod said:

 

What condition (algorithm) do you use to change the captions? Is it possible to use it only on the client side without loading the server every time?

uniTimer1.OnTime

uniPanel.Caption := DateTime;

I know I can only do it on the client side, but that's not the only thing I'm doing on this timer event. I thought that the uniPanel.Caption is also updated along with the uniDBGrid on the form and that there are many components that are hidden but are updated periodically (via the timers) does it affect the overall time to hide the mask?

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...