Performance issue

Vikcia
2008-08-28
2013-05-01
  • Vikcia

    Vikcia - 2008-08-28

    Hi. I need a little more performance. When use Full screen, rotated portrait, client side resize - auto (server side didn't work at all. why?), update ASAP on Windows Mobile, performance isn't acceptable... Is there possibility to do anything (tried to use unsave code for setpixel, also tried speed up copyrect, but performance still suffer:-( )? BTW, there is one profiler for .net cf : eqatec clr profiler.

     
    • Rocky Lo

      Rocky Lo - 2008-09-06

      - May I know what VNC server favor you are using?
      - Please turn off "Update ASAP".  It should be used only when the connection is slow so that the viewer redraws more frequently.  If the connection is reasonably fast, it is better to turn it off.

      I think implementing zlib encoding should be the way to go but don't have the time to do this...

       
    • Vikcia

      Vikcia - 2008-09-08

      Server side scaling now works - with UtraVNC 1.0.5.

      I set on server lowest resolution as possible, server side scaling 1/3 or 1/4 - performance is acceptable, but screen is a little blurry and distorted (where is biggest screen changes). For example Mocha VNC trial works much faster and without server side scaling (pity, that Mocha VNC doesn't support command line parameters).  I noticed that, when Mocha VNC updates picture, it updates very small part of the screen, .Net VNC Vierwer updates much larger part (aproximately 1 mm on Mocha VNC vs 5 mm on .Net VNC) Very clear difference between these clients, when on server start Windows Media player with mp3 and some visualization.

      I played a little with clr profiller and I think, that biggest slowdown is because picture needs to be resized. Something wrong is at View.cs OnPaint event.
      1. Maybe I am wrong, but when you lock framebuffer LockFrameBuf, there is big slowdown (in the background some thread intensively works with bitmap and blocks repaint). Maybe there can be some optimization? For example, cached bitmap which will get all updates, and every 0.5 sec will synchronize with painted bitmap...
      2. You use graphics.DrawImage(framebuf, destRect, sourceRect, GraphicsUnit.Pixel). If I understandd right, on every repaint this method resizes bitmap. If this framebuf would be resized once (when initializing View) and later setting pixel on this resized bitmap, maybe performance would be better?

      I think zlib would make situation even worse. On PC .Net VNC Client works fast and there no need to optimize performance. On pda and smartphone performance is very limited, so if you use zlib you save traffic, but loose

       
    • Rocky Lo

      Rocky Lo - 2008-09-20

      This is really good Vikcia.  I always wished I had a way to tell what the slowest part would be, but never got the time and tool to complete the job.

      a) Blurry and distorted screen when using server-side scaling - this is UltraVNC's behavior, but if the viewer performs better the effect will not be as obvious...

      b)  You are right in saying that, when the background thread is busy processing updates from the server, the UI thread cannot paint the screen.  With that said I don't think drawing more frequently will help.  In fact "Update ASAP" is for this purpose but it is only useful for slow connections.

      c) If client side scaling is not enabled, I think DrawImage() does not need to resize.

      Do you know if the performance of SetPixel() is acceptable or not?  When I wrote this I just hoped that it would work on all devices so I did not seek another way to update the buffer.

       
    • Vikcia

      Vikcia - 2008-09-30

      I see, that OnPaint event on initial load takes 11 seconds - one third of time. Most of the time it draws. One repaint will take 33 miliseconds, but for initial load event fires 240 times. There can be done optimisation: why repaint so often? Maybe would be better repaint every second? And then repaint not only some rectangle, but all picture? For example initial load takes 30 seconds, so we need only 30 repaints, but not 240. And needed time will change from 10 seconds to 1 second (so other thread, which gets data from server, faster will get lock on frameBuff).

      Next.
      Biggest slowdown is ReadHexRect. 3 calls which takes 26 seconds. Maybe there also can be done some optimization? I will investigate further...

      There is problem, that on Windows Mobile 5 doesn't works keyboard (SIP).

       
    • Vikcia

      Vikcia - 2008-10-01

      About SIP:
      Understood - it's my fault. I added button on the form - so, event doesn't fires, because button get's focus and forms event onkeypress doesn't fire.

       
    • BobD

      BobD - 2008-11-21

      Hello,

      Rocky, First and formost I really just wanted to thank you and all those who created this C# .Net VNC client. I have used it as a base for a very stripped down, very custom VNC client.

      I too spent a lot of time trying to get the client to paint as fast as Real VNC or Tight VNC.  While I modified the ReadRawRect() function severly - I dont think it gave me as big a boost as the change I made to how often I allowed the client to call DrawImage().

      When I modifed the Conn class to update the client "during periods of no more framebuffer update messages coming in" the client sped up dramatically.  (I only supprt the RAW format)

      Snippets folow - all this is just FYI to you and those that follow.

      Bob

      private void ReadRawRect(ref Rectangle rect)
              {

                  Int32 rgboffset = 0;
                  Rectangle r = new Rectangle(rect.X, rect.Y, rect.Width, 1);
                  rgbValues = ReadBytes(rect.Width * rect.Height * bytesPp);
                            
                 
                  //use these Min an Max values to determine the overall rectangle that needs refreshing when
                  //the server stops sending data for a "screen udate".  Waiting until we "think" all
                  //the screen updates have been transmitted makes this faster...
                  //previous implementation would cause a re-paint after every framebuffer update...slower
                  minX = Math.Min(minX, rect.X);
                  minY = Math.Min(minY, rect.Y);
                  maxX = Math.Max(maxX, rect.X + rect.Width);
                  maxY = Math.Max(maxY, rect.Y + rect.Height);

                  //BitBlit the framebuffer data into the Bitmap!!
                  try
                  {
                      for (int i = 0; i < rect.Height; i++)
                      {
                          bmpData = bmpFrameBuffer.LockBits(r, ImageLockMode.WriteOnly, bmpFrameBuffer.PixelFormat);
                          Marshal.Copy(rgbValues, rgboffset, bmpData.Scan0, rect.Width * bytesPp);
                          rgboffset += rect.Width * bytesPp;
                          bmpFrameBuffer.UnlockBits(bmpData);
                          r.Y = rect.Y + i + 1;
                      }
                  }
                  catch //(Exception ex)
                  {
                      //Console.WriteLine("Argument Exception: " + ex.Message);
                  }

                
                 
                  dirty = true;

              }

      private void Start()
              {

                  try
                  {
                     
                      while (!termBgThread)
                      {
                          if (!stream.DataAvailable)
                          {
                             if (ScreenUpdate != null)
                             {
                                  if (dirty == true)
                                  {
                                      //Heres a chance to update the screen when we think all the changes have
                                      //been sent for the most recent "screen changes" on the server
                                      // no data available from the server and "dirty = true" means its
                                      //time to update the screen.

                                      //prior implementation would update the client after every individual
                                      //framebuffer square (40 x 30 pixels)sent from the server.

                                      Rectangle rectDirty = new Rectangle(minX, minY, maxX, maxY);
                                      ScreenUpdate(rectDirty);
                                      dirty = false;

                                  }
                              }

                              continue;
                          }

      etc
      etc
      etc

       
      • BobD

        BobD - 2008-11-21

        this line did not make the edit in snippet -

        Thread.Sleep(40); //give GDI a chance to do its work - GDI is slow in .Net

        goes in this block

        Rectangle rectDirty = new Rectangle(minX, minY, maxX, maxY);
        ScreenUpdate(rectDirty);
        dirty = false;
        Thread.Sleep(40); //give GDI a chance to do its work - GDI is slow in .Net

         

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks