Forum Archive

ui.delay usage

Phuket2

With my scrolling VirtualView, I wanted to create a stress test for it. I didn't want to insert the stress test code into my class. So I created the Stress Class below. After my VirtualView is presented from my main, I then just create an instance if the Stress class passing it a reference to the VirtualView Class.
So all it does is scroll the view on page at a time. When it reaches the end of the scrollable content, it starts from the top of the list again.
Maybe some will think I am manic :) but I want a test like this. I will run when sleeping when my iPad is charging.

What I don't know, if I am creating some unstable conditions by calling the code like this.

I have only run with the Stress object for 15mins or so. The functionality all works fine. But I have had the editor crash a few times when after running this. I am not crashing at runtime.

I understand, this could be something with 1.6 or I could be abusing the use of ui.delay()

Any thoughts appreciated.

class Stress(object):
    # an auto scroller for VirtualView class
    # to stress test it. 
    def __init__(self, obj, delay = .1):
        import console, time 

        # trying for saftey
        ui.cancel_delays()

        # no sleeping...
        console.set_idle_timer_disabled(True)

        self.obj = obj
        self.delay = delay
        # record the start time
        self.start = time.time()
        ui.delay(self.auto_scroll, 2)


    def auto_scroll(self):
        # the scrollview
        sv = self.obj.sv

        # current offset of the scrollview
        v_offset = sv.content_offset[1]
        # calc new_offset, to be + one page 
        new_offset = v_offset + sv.height

        # wrap around if we reach the bottom if the list
        if new_offset > sv.content_size[1]:
            new_offset = 0

        sv.content_offset = (0, new_offset )

        ui.cancel_delays()
        ui.delay(self.auto_scroll, self.delay)

    # __del__ is not being called...
    # moved the running duration code into the
    # VirtualView object.
    #def __del__():
        #ui.cancel_delays() 
        #print time.time() - self.time()
Phuket2

Oh, I just put a call to ui.cancel_delays() Into the will_close of the VirtualView class. I just seen some strange behaviour that made me think I need to do that.

JonB

a delay of 0.1 seems pretty short to me! at least randomly insert a larger delay. if your virtualview code hasnt finished, then things might be getting behind ... that works differently than touch events i think, if main thread is busy, i think the touch event is delayed (not 100% sure sbout that). you might want @on_main_thread for the bits that update the scroll position.

JonB

oh i misread your problem... check on_screen in the start of autoscroll, and if not onscreen, then return. remember will_close is called on the main thread, while autoscroll is a delayed call running in its own thread, so there is a chance willclose gets called while you are in autoscroll, in which case your cancel all delays wont work, and the method will continue to run.

Phuket2

@JonB, there really is not a problem as such. It's really about understanding how stable all this is and if the way I use it, makes the environment unstable or not. Does not make sense to stress test something with flawed code.
I dont need to worry about if onscreen or not, because the view containing the scroll view is presented before I create the Stress class, so ip for sure its on screen.
But it seems one problem I did have was that when I exited the app, I was not calling ui.cancel_delays. Meaning ui.delay code can still be trying to execute.
The VirtualView class has a clear exit point, 'will_close'. So I call ui.cancel_delays there.
I would prefer that the Stress class del method was called on the program exit so I could clean up without involving the VirtualView class. But it does not.

I take your point about the short time for delay. But who knows how long it will take to complete a cycle (we don't want it to slow) . So I will just try some signalling. True when executing the code ( if executing, bug out) , then set to False when finished so it does not get reenterent. I think that should sovle that problem in a reasonable way.

Phuket2

Another misunderstanding by me, I think. I changed the class as below.it appears it will never be reenterent. Lowest time for delay, also delayed in the building of my cells. You can see I put a print statement in the code if we tried to re enter the code and it was busy. I could not make it happen. So I am guessing ui.delay is not just threading, but threading with a queue.
Really, I am not sure. But it looks that way.

class Stress(object):
    # an auto scroller for VirtualView class
    # to stress test it. 
    def __init__(self, obj, delay = .1):
        import console, time 

        # trying for saftey
        ui.cancel_delays()

        # no sleeping...
        console.set_idle_timer_disabled(True)

        self.obj = obj
        self.delay = delay
        self.busy = False
        # record the start time
        self.start = time.time()
        ui.delay(self.auto_scroll, 2)


    def auto_scroll(self):
        if self.busy:
            print 'i was busy'
            ui.cancel_delays()
            ui.delay(self.auto_scroll, self.delay)
            return 

        self.busy = True

        # the scrollview
        sv = self.obj.sv

        # current offset of the scrollview
        v_offset = sv.content_offset[1]
        # calc new_offset, to be + one page 
        new_offset = v_offset + sv.height

        # wrap around if we reach the bottom if the list
        if new_offset > sv.content_size[1]:
            new_offset = 0

        sv.content_offset = (0, new_offset )

        ui.cancel_delays()
        ui.delay(self.auto_scroll, self.delay)
        self.busy = False

    # __del__ is not being called...
    # moved the running duration code into the
    # VirtualView object.
    #def __del__():
        #ui.cancel_delays() 
        #print time.time() - self.time()

JonB

no, it wont ever appear reentrant because you call the delay at the end of the function. if you started two delays at slightly different times, i think it would behave differently. but note that you need a way for this to STOP what it is doing! a flag or checking onscreen would work. cancel delays will work sometimes, but is not guaranteed.

Phuket2

@JonB . Thanks.
I ran this last night on my Virtual View for 7 hours. It created 4.8 million cells scrolling. Each cell contained 2 labels populated with data from faker, a image with a random built in image loaded, and a button with a background picture.
Everything still stable after I stopped it.
So that's a reasonable stress test

Phuket2

Phuket2

@JonB , I can be such a fool sometimes. You gave me the answer, I was just not listening correctly .
Now when I enter the auto_scroll method, I am checking to see if the view is onscreen. It it's not, I do del self and return. Then my del method is called, where I can clean up properly. It also now removes any dependence from the class that it is stressing. Meaning it could be used to test a number of ui interfaces that for what ever use a lot of memory. Also can expand it a little to collect some stats along the way.

But thanks again. Good to have that done before the F1 today :)