Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

canvas.show() is slow with psycho back-end and 'difficult' canvas

edited June 2016 in OpenSesame

Hi all,

Ran into some big delays for canvas.show() function when using psycho back-end with a 'difficult' canvas.

I tested this by copying the Listing 2 example and adding Canvas3 with many randomly positioned fixation dots inspired by Example 2 here.

# Prepare canvas 1 and 2
canvas1 = canvas(exp)
canvas1.text('This is the first canvas')
canvas2 = canvas(exp)
canvas2.text('This is the second canvas')
# Prepare canvas 3 (without auto_prepare=False)
from random import randint
canvas3 = canvas()
for i in range(1000):
        x = randint(0, canvas3.width)
        y = randint(0, canvas3.height)
        canvas3.fixdot(x, y)
# Show canvas 1
t1 = canvas1.show()
# Sleep for 95 ms to get a 100 ms delay
self.sleep(95)
# Show canvas 2
t2 = canvas2.show()
# Sleep for 95 ms to get a 100 ms delay
self.sleep(95)
# Show canvas 3
t3 = canvas3.show()
# The actual delay will be 100 ms, because stimulus
# preparation time is not included. This is good!
print 'Actual delay t2-t1: %s' % (t2-t1)
# Sadly not for the 'difficult' canvas3
print 'Actual delay t3-t2: %s' % (t3-t2)

Gives the expected output for the legacy and xpyriment back-ends, but a big delay for the 'difficult' canvas3 (t3-t2) using the psycho back-end:

psycho back-end:

Actual delay t2-t1: 100.428051515

Actual delay t3-t2: 385.974423159

legacy back-end:

Actual delay t2-t1: 96

Actual delay t3-t2: 96

xpyriment back-end:

Actual delay t2-t1: 100.0

Actual delay t3-t2: 100.0

Notes:

  • I used opensesame_3.0.7-py2.7-win32-3 on Win7 64 bit with a 60Hz monitor to test this
  • Because I do not use auto_prepare=False so preparing with xpyriment back-end takes long
  • opensesame_3.1.0a41-py2.7-win32-1 and opensesame_2.9.7-win32-1 have the same delays
  • The actual delays match with the delays I recorded with a high speed camera

Best,

Jarik

Comments

  • edited June 2016

    Hi Jarik,

    Thanks for this benchmark.

    This results from the fact the PsychoPy doesn't prepare canvases in the same way that the other back-ends do; it does create stimulus objects in advance, but they are rendered only at the moment that the canvas is shown (i.e. OpenSesame calls draw() and flip() at the same time). Rendering is pretty fast, so this is usually fine; but when you have 1000+ stimuli it becomes notably slow. So that's basically inherent to how PsychoPy works.

    To be fair to PsychoPy, if you use psychopy directly, you can control when you call draw() and flip(), and this gives you better control of the timing:

    from psychopy import visual
    
    t0 = clock.time()
    # Can take a long time, but doesn't update the display
    for i in range(1000):
        visual.Circle(win).draw()
    t1 = clock.time()
    # Updates the display almost instantaneously
    win.flip()
    t2 = clock.time()
    
    print('draw() time: %.2f ms' % (t1-t0))
    print('flip() time: %.2f ms' % (t2-t1))
    

    But you cannot, for example, prepare multiple canvases with many objects in advance, and then show them in rapid succession. For that legacy and xpyriment are better.

    Cheers!
    Sebastiaan

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • edited 8:48PM

    Hi Sebastiaan,

    Thank you! Crystal clear now!

    One minor thing is your example script prints seconds instead of milliseconds, so it should be:

    print('draw() time: %.2f s' % (.001 * (t1-t0)))
    print('flip() time: %.2f s' % (.001 * (t2-t1)))
    #OR
    print('draw() time: %.2f ms' % (t1-t0))
    print('flip() time: %.2f ms' % (t2-t1))
    

    Best,

    Jarik

  • edited 8:48PM

    Right!

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

Sign In or Register to comment.