A way to avoid that ?

A way to avoid that ?

Postby Didier Bur » Fri Jan 14, 2011 9:41 am

Hi all,
When a script has a bunch of entities to create/draw, after several seconds it shows the hourglass until it finishes its job, then redraws the view entirely. Outputing messages or progressbar doesn't prevent that.
Anyone knows why it does that and if there is a workaround ?
0
Didier Bur
Ecole Nationale Supérieure d'Architecture de Nancy (F)
User avatar
Didier Bur 
 

Re: A way to avoid that ?

Postby thomthom » Fri Jan 14, 2011 11:34 am

The work that the Ruby script produces blocks any other operations, including updating the UI.

Fredo uses a timer to split up the work into smaller chunks in order to produce a more responsive UI. I have experimented with the same but found the processing time to multiply many times. Didn't feel the benefit of a responsive UI was worth the extra time.

My test project:
worker.rb

worker.png

TT_Test.test_basepoint # Normal loop. For speed reference.
TT_Test.test_walker(true) # disable UI
TT_Test.test_walker(false)
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid that ?

Postby Didier Bur » Fri Jan 14, 2011 12:18 pm

Thanks TT, so I'm not alone facing this problem :(

P.S.: first time ever that I see "view.draw2d( GL_QUADS, fill )" working OK. Each time I've used that it always drew the quads in a black color, no matter the drawing color set before !
0
Didier Bur
Ecole Nationale Supérieure d'Architecture de Nancy (F)
User avatar
Didier Bur 
 

Re: A way to avoid that ?

Postby thomthom » Fri Jan 14, 2011 12:33 pm

Didier Bur wrote:P.S.: first time ever that I see "view.draw2d( GL_QUADS, fill )" working OK. Each time I've used that it always drew the quads in a black color, no matter the drawing color set before !


view.draw2d has worked with GL_QUADS and the other fill styles.
But view.draw hasn't. That was recently fixed in SU8M1. In addition, view.draw and view.draw2d now makes use of the alpha channel in Sketchup::Color ! That's a very nice fix as it allows for nicer and better UIs.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid that ?

Postby thomthom » Fri Jan 14, 2011 12:35 pm

Didier Bur wrote:Thanks TT, so I'm not alone facing this problem :(

People have tried using threads to offload the work, but due to the nature of threads in SU Ruby 1.8 it doesn't help in our case.
Even doing webdialogs, - but the ruby working blocks even the webdialog.

:(
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid that ?

Postby TIG » Fri Jan 14, 2011 1:17 pm

Completely off the wall idea... and untried :roll:
tid=UI.start_timer(0){your_code_here}
So your_code now executes outside of the main Sketchup process - rather like my ImageAnimator does...
If all geometry changes etc were kept inside a group [perhaps hidden] until the end when you can explode it if needed then you shouldn't notice it till it's done ?
Not sure how model.start/commit_operation might work inside of a UI.timer :shock:
You could perhaps still report progress through a webdialog progressbar ??

Just ideas [as someone else often says]...
0
TIG
User avatar
TIG 
Global Moderator
 

Re: A way to avoid that ?

Postby thomthom » Fri Jan 14, 2011 1:27 pm

TIG wrote:Completely off the wall idea... and untried :roll:
tid=UI.start_timer(0){your_code_here}

The sample I posted above splits the work into timed execution.

TIG wrote:So your_code now executes outside of the main Sketchup process

No - it's not outside. It's just delayed. If you add the whole lot of work to be done into one time interval it'll still freeze up the UI.

What Fredo did, and what I tried, was to split the work into smaller chunks which is done by the timer. After each chunk is done, other things are allowed to complete - until the timer triggers again. The trouble is balancing. Evenever the timer chunk doo too much work you'll find the UI freezing again.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid ? (white screen)

Postby Jim » Fri Jan 14, 2011 2:01 pm

Try to avoid adding individual geometry (add_face) if add_faces_from_mesh() or fill_from_mesh() can be used.

Use model.start_operation/commit_operation and take advantage of the 2nd parameter.

As has been said, you can add geometry while also keeping SketchUp responsive by partitioning the work and adding each partition in a timer block. This will likely make the overall operation even slower, but the user will be able to cancel or even interact with the model while in progress.

Here's an animation I made some time ago showing adding faces in a timer block while allowing interaction with the model.

viewtopic.php?p=234026#p234026

0
Last edited by Jim on Fri Jan 14, 2011 2:07 pm, edited 4 times in total.
Hi

Jim 
Global Moderator
 

Re: A way to avoid that ?

Postby TIG » Fri Jan 14, 2011 2:04 pm

thomthom wrote:
TIG wrote:Completely off the wall idea... and untried :roll:
tid=UI.start_timer(0){your_code_here}

The sample I posted above splits the work into timed execution.

TIG wrote:So your_code now executes outside of the main Sketchup process

No - it's not outside. It's just delayed. If you add the whole lot of work to be done into one time interval it'll still freeze up the UI.

What Fredo did, and what I tried, was to split the work into smaller chunks which is done by the timer. After each chunk is done, other things are allowed to complete - until the timer triggers again. The trouble is balancing. Evenever the timer chunk doo too much work you'll find the UI freezing again.

Sorry [great minds think alike] I hadn't looked at your or Fredo's code... ;)
You could split the processing into tiny pieces - it's usually iterating lots of values that see to 'whiteout' ?
max=1000;i=0;tid=UI.start_timer(0,true){your_code(i);i+=1;UI.stop_timer(tid)if i==max}
You'd actually set 'max' from the complexity of the actions as in 0.to(max)... The your_code(arg) takes 'arg' and knows which step to execute in the iteration etc... This way an iteration is done using the one timer repeating till it's done - one step at a time - much slower I'd expect but then hopefully 'whiteout' free... :?
0
TIG
User avatar
TIG 
Global Moderator
 

Re: A way to avoid that ?

Postby thomthom » Fri Jan 14, 2011 2:07 pm

Yes - as long as the operations a kept small it'll prevent whiteout. But it can take 3, 4, 5, 6 ... times longer! :?
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid ? (white screen)

Postby thomthom » Fri Jan 14, 2011 2:12 pm

Jim wrote:Try to avoid adding individual geometry (add_face) if add_faces_from_mesh() or fill_from_mesh() can be used.

This applies to any SketchUp operation. entities.erase_entities is faster than lots of entity.erase!. entities.transform_entities is faster than individual transformations.
If you have lots of different transformations that only move things around, use Entities.transform_by_vectors. <- even allows you to move vertices.
In Vertex Tools, when you move, rotate and scale, I first run a pass where I transform the position of the vertex, then get the vector from the old position to the new and use Entities.transform_by_vectors. Despite the extra pass it's faster as any method manipulating geometry has a high performance tax so you save lots of time by calling these kind of methods as rarely as you can.
0
Thomas Thomassen — SketchUp Monkey & Coding addict
List of my plugins and link to the CookieWare fund
User avatar
thomthom 
PluginStore Author
PluginStore Author
 

Re: A way to avoid that ?

Postby Dan Rathbun » Fri Jan 14, 2011 5:47 pm

thomthom wrote:Yes - as long as the operations a kept small it'll prevent whiteout.

"whiteout" = "ghost window"

MSDN at Windows API Reference, in PeekMessage Function wrote:If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the user to move it, resize it, or even close the application. However, these are the only actions available because the application is actually not responding. When an application is being debugged, the system does not generate a ghost window.


When Sketchup goes into "ghost mode", you will see it listed as "Skethcup (not responding)" in the Task Manager.

First of all, changing the interval that Windows uses to determine when a process is "not responding", although possible, causes other major headaches systemwide. Also, I think that it requires a registry change and reboot (if memory serves me,) so is not a serious option for us.

I would attempt to force a PeekMessage system call, for Sketchup's thread, within the "responding inteval" (can't remember offhand what it is.)

So any way it's not your add entities block that needs to go inside a UI.start_timer proc, ... it's a API call to PeekMessage, like:

Code: Select all
begin
  peek = UI.start_timer(interval, true) {
   peek_window_msg()
  }
  do_create_lots_of_model_entities()
  UI.stop_timer(peek)
end


where, peek_window_msg() would be a method that sets up and makes the proper API call. (It should NOT delete any messages from the queue, basically it is just acknowledging to the system that Sketchup knows that messages are pending to be processed.)

It would be better (for us,) if something like this was built into the main() loop (prodived C++ has something like a start_timer function.) Perhaps John Hauswirth might know if it's possible.
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: A way to avoid that ?

    Postby Dan Rathbun » Fri Jan 14, 2011 5:50 pm

    The other option, would be to "fool" the system into thinking that Sketchup was being debugged, during the long add entities block.
    0
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: A way to avoid that ?

      Postby thomthom » Fri Jan 14, 2011 5:54 pm

      Have you used that PeekMessage thing?
      0
      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund
      User avatar
      thomthom 
      PluginStore Author
      PluginStore Author
       

      Re: A way to avoid that ?

      Postby Jim » Fri Jan 14, 2011 5:57 pm

      That would be awesome if it works. :thumb:
      0
      Hi

      Jim 
      Global Moderator
       

      Re: A way to avoid that ?

      Postby Dan Rathbun » Fri Jan 14, 2011 6:35 pm

      thomthom wrote:Have you used that PeekMessage thing?

      I haven't had time yet myself, (as I have not yet written any code that creates a long Ruby processing delay.)

      Also.. it has been a few months since I read that MSDN page, and just noticed the last item about debug mode. (A quick look into this, seems much more complex. A debugger object needs to be created and attached to the Sketchup process, etc.)
      0
      Last edited by Dan Rathbun on Fri Jan 14, 2011 11:52 pm, edited 1 time in total.
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        Re: A way to avoid that ?

        Postby Dan Rathbun » Fri Jan 14, 2011 11:50 pm

        Dan Rathbun wrote:A debugger object needs to be created and attached to the Sketchup process, etc.

        I am wary of releasing anything that does something this drastic.. and because BugSplat! is also likely a (post-mortem) debugger implementation... the last thing I want to do is break the BugSplat! functionality.
        0
          I'm not here much anymore. But a PM will fire email notifications.
          User avatar
          Dan Rathbun 
          PluginStore Author
          PluginStore Author
           

          Re: A way to avoid that ?

          Postby thomthom » Tue Jan 25, 2011 5:02 pm

          Haaaaaaah!!!!!


          Just made a really quick and dirty hack - calling PeekMessage at the inner most loop:

          Code: Select all

            PeekMessage 
          TT::Win32::API.new('PeekMessage' 'PLIII''I''user32')
            
            
          def self.refresh
              msg 
          ' ' 2048
              r 
          PeekMessage.call(msg0000)
            
          end


          worked perfectly!!!!

          :berserk: :berserk:

          Though I think one might want to time the peek after a given short enough time. (And msg needs to be of correct size...)
          0
          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund
          User avatar
          thomthom 
          PluginStore Author
          PluginStore Author
           

          Re: A way to avoid that ?

          Postby thomthom » Tue Jan 25, 2011 5:08 pm

          tried using a timer to sending PeekMessage - while the inner loop did its thing.
          didn't work. the inner loop blocked it. So the inner loops need to call this. which means that when SU's methods are processing they will probably block the UI . like intersecting many entities.

          But in many cases this can really help.

          of course - OSX users are out of luck....
          0
          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund
          User avatar
          thomthom 
          PluginStore Author
          PluginStore Author
           

          Re: A way to avoid that ?

          Postby Jim » Tue Jan 25, 2011 5:27 pm

          Oh, that's interesting.

          Couple a thoughts - terminate the message with a c language null: '\0' (just in case?) The size should still be 2048 including the null.

          More obviously, you don't need to peek every loop iteration - so something like:

          refresh if (loop_counter % 500 == 0)
          0
          Hi

          Jim 
          Global Moderator
           

          Re: A way to avoid that ?

          Postby thomthom » Tue Jan 25, 2011 6:15 pm

          Jim wrote:Couple a thoughts - terminate the message with a c language null: '\0' (just in case?)

          Isn't that just for strings?
          The string I pass is just a data buffer that will be filled with binary data - which one has to extract.

          Jim wrote:More obviously, you don't need to peek every loop iteration - so something like:
          refresh if (loop_counter % 500 == 0)

          Yes - more pragmatic than calculating time. I like it, it's KISS.
          0
          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund
          User avatar
          thomthom 
          PluginStore Author
          PluginStore Author
           

          Re: A way to avoid that ?

          Postby Jim » Tue Jan 25, 2011 6:37 pm

          thomthom wrote:Isn't that just for strings?


          Yeah, I made an assumption the message was a c character array.
          0
          Hi

          Jim 
          Global Moderator
           

          Re: A way to avoid that ?

          Postby thomthom » Tue Jan 25, 2011 6:40 pm

          Jim wrote:
          thomthom wrote:Isn't that just for strings?


          Yeah, I made an assumption the message was a c character array.

          No, it's a MSG structure. Just didn't bother to work out exactly how large it is. (probably will be making a wrapper for this.) So I just make a large buffer while I quickly tested it.
          ...if I don't need the returned message, would it be ok to just send an empty buffer?
          0
          Thomas Thomassen — SketchUp Monkey & Coding addict
          List of my plugins and link to the CookieWare fund
          User avatar
          thomthom 
          PluginStore Author
          PluginStore Author
           

          Re: A way to avoid that ?

          Postby Dan Rathbun » Fri Feb 11, 2011 3:44 am

          Dan Rathbun wrote:
          thomthom wrote:Yes - as long as the operations a kept small it'll prevent whiteout.

          "whiteout" = "ghost window"

          ...[snip]...

          I would attempt to force a PeekMessage system call, for Sketchup's thread, within the "responding inteval" (can't remember offhand what it is.)

          So any way it's not your add entities block that needs to go inside a UI.start_timer proc, ... it's a API call to PeekMessage, like:

          Code: Select all
          begin
            peek = UI.start_timer(interval, true) {
             peek_window_msg()
            }
            do_create_lots_of_model_entities()
            UI.stop_timer(peek)
          end


          where, peek_window_msg() would be a method that sets up and makes the proper API call.

          @ThomThom & friends, ... I stumbled across where I saw the 'whiteout' interval.
          It's specified on the IsHungAppWindow Function reference page.
          Says 5 seconds.

          So perhaps:
          Code: Select all
          begin
            interval =( Sketchup.version.to_i<8 ? 4 : 4.9 )
            peek = UI.start_timer(interval, true) {
             peek_window_msg()
            }
            do_create_lots_of_model_entities()
            UI.stop_timer(peek)
          end
          0
            I'm not here much anymore. But a PM will fire email notifications.
            User avatar
            Dan Rathbun 
            PluginStore Author
            PluginStore Author
             

            Re: A way to avoid that ?

            Postby thomthom » Fri Feb 11, 2011 8:34 am

            Interesting - from that article.
            An application is considered to be not responding if it is not waiting for input, is not in startup processing, and has not called PeekMessage within the internal timeout period of 5 seconds.


            Though, it seems one can't reply on that time.
            The Windows timeout criteria of 5 seconds is subject to change.


            I have set the interval to a handful of times per second because I use it to force SU to update its statusbar.
            0
            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund
            User avatar
            thomthom 
            PluginStore Author
            PluginStore Author
             

            Re: A way to avoid that ?

            Postby Dan Rathbun » Fri Feb 11, 2011 6:04 pm

            I still wonder if a peek message loop could be written into the commit_operation API method.
            0
              I'm not here much anymore. But a PM will fire email notifications.
              User avatar
              Dan Rathbun 
              PluginStore Author
              PluginStore Author
               

              Re: A way to avoid that ?

              Postby Dan Rathbun » Fri Feb 11, 2011 6:09 pm

              And there is another 'nutty' thing that happens. When the ghost window is created, it has a different handle then the "real" application window. There are a couple functions that return the other handle, depending on which window handle you grab. (Strange that the IsHungAppWindow function is "not for general use.")
              0
                I'm not here much anymore. But a PM will fire email notifications.
                User avatar
                Dan Rathbun 
                PluginStore Author
                PluginStore Author
                 

                Re: A way to avoid that ?

                Postby thomthom » Fri Feb 11, 2011 7:17 pm

                Dan Rathbun wrote:I still wonder if a peek message loop could be written into the commit_operation API method.

                I made a wrapper iterator that will take an enumerator objects and wrap it in between start and commit operation while updating the progress in the statusbar, kept alive by PeekMessage limited to a certain interval. Works really well for simple one-iteration operations.
                0
                Thomas Thomassen — SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund
                User avatar
                thomthom 
                PluginStore Author
                PluginStore Author
                 

                Re: A way to avoid that ?

                Postby nikusknx » Tue Jun 03, 2014 3:35 pm

                Update for Sketchup 2014 :

                Code: Select all
                require "Win32API.rb
                msg = "\000" * 36
                peekMessage = Win32API.new('user32','PeekMessage' , 'PLIII', 'I')
                peekMessage.call( msg, 0, 0, 0, 0x0000 ) != 0
                1
                User avatar
                nikusknx 
                Kubity Support
                Kubity Support
                 

                SketchUcation One-Liner Adverts

                by Ad Machine » 5 minutes ago



                Ad Machine 
                Robot
                 



                 

                Return to Developers' Forum

                Who is online

                Users browsing this forum: Bing [Bot], bobtriedit, select99s, vKevlar and 9 guests

                Visit our sponsors: