Canvas performance problem

Hi, I am using the following esp32 board and ili9341 display:

  • LilyGO T7 v1.4 with 4 MB PSRAM
  • 2.8" ili9341 display 320x240
  • lv_micropython GENERIC_SPIRAM firmware compiled with linux

I fill a canvas using canvas.set_px():

  • when canvas size is 320x180, or smaller, the program is ok and draws 2700 pixels per second (21 seconds for 320x180 pixels)
  • when canvas size is 320x181 (just one line bigger) it slows down a lot, it takes 32 minutes to complete (30 pixels per second)!!!

Why is it getting so slow, what’s going wrong?

The program I used:

import lvgl as lv
from ili9XXX import ili9341, LANDSCAPE
import time

CANVAS_WIDTH = 320
CANVAS_HEIGHT = 180 # 180 OK, 181 ULTRA-SLOW

lv.init()
disp = ili9341(miso=19, mosi=23, clk=18, cs=5, dc=21, rst=26, width=320, height=240, rot=LANDSCAPE)
scr = lv.scr_act()
canvas = lv.canvas(scr)
buf = bytearray(CANVAS_WIDTH * CANVAS_HEIGHT * lv.color_t.SIZE)
canvas.set_buffer(buf, CANVAS_WIDTH, CANVAS_HEIGHT, lv.img.CF.TRUE_COLOR)
color = lv.color_make(0, 0, 255)
lv.scr_load(scr)

start_ms = time.ticks_ms()
for x in range(0, CANVAS_WIDTH):
	for y in range(0, CANVAS_HEIGHT):
		canvas.set_px(x, y, color)
elapsed_ms = time.ticks_diff(time.ticks_ms(), start_ms)
print("elapsed seconds: {}".format(elapsed_ms / 1000))
print("pixels/second: {}".format((CANVAS_WIDTH * CANVAS_HEIGHT) / (elapsed_ms / 1000)))

Hi @Escher!

Could you explain your motivation for writing many pixels to canvas with set_px?
This is very inefficient, and there are other ways to do that much faster.

If you need to write many pixels to canvas I would suggest writing directly to buf and calling invalidate to redraw the canvas.
If you want to write efficiently to buf I recommend using the viper code emitter which would give you close-to-native speed for tasks such as filling / modifying byte arrays.

Thanks for your suggestions! It’s a 2D realtime simulation.
I will try your proposed solution.

Personally I’m still curious as to why the additional line causes that much of a change; I’ll add this to my list of things to experiment with when I have time.

on a twatch-2020 it’s a disaster !
even in 240x240.

@embeddedt I’m not sure, but this may be related to many cache misses for each pixel being written.
Maybe the additional line pushes some buffers over the cache size.
He is using psram so all gc allocated buffers are on the slow spi-ram.