Why is image (re: picture) display so slow?
|Status:||In Progress||Start date:||18 Sep 2019|
|Target version:||PiBox - 1.1.0 - Upgrades|
|Severity:||04 - Low|
Browsing through pictures with a touchscreen is very slow. Loading images should be fast with Cairo/gtk so this is probably some kind of integration problem with the touchscreen and command processing in pipics.
#4 Updated by Hammel about 1 month ago
Added timestamps to logging in pipics. This is what I see:
5de43995 [touchProcessor.c:0345] INFO TSLIB: sample 1575238037.819253: 773 224 255 5de43995 [touchProcessor.c:0347] INFO TSLIB: last 0.000000: 0 0 0 5de43995 [touchProcessor.c:0382] INFO ABS callback is NULL 5de43995 [touchProcessor.c:0394] INFO --- Region 2 1 5de43995 [touchProcessor.c:0411] INFO Calling registered touch callback with region: 5 5de43995 [ pipics.c:0159] INFO Next image region 5de43995 [ pipics.c:0072] INFO Getting next image. 5de43995 [ pipics.c:0479] INFO Entered 5de43995 [ pipics.c:0495] INFO Trying to display file: ./sda1/20170202_124802.jpg 5de43995 [ pipics.c:0500] INFO window w/h: 800 / 480 5de43995 [ pipics.c:0509] INFO Creating pixbuf from file 5de43995 [touchProcessor.c:0340] INFO TSLIB: not pressed. 5de43997 [ pipics.c:0511] INFO Loaded image from file 5de43998 [ pipics.c:0513] INFO Applied orientation 5de43998 [ pipics.c:0533] INFO Scaling image 5de43998 [ pipics.c:0537] INFO image w/h: 360 / 480
So it takes two seconds to read the image and another second to scale it. I'm not sure if I can actually speed that up without requiring pre-managed images (scaled to fit beforehand), which I don't want to do. Also, it doesn't appear the touchscreen handling is the problem. That goes off without a hitch - no delays there.
I also noticed quit isn't always immediate when the upper right region (stop region) is pressed. But if you press and hold it is. The problem there seems to be that it can look like a press in region 2/1 when it should be 2/0 unless you press and hold, ie a quick tap in region 2/0 can sometimes show up as 2/1. Not sure why that is but it seems more like a tslib (or lower, like the hardware itself) problem.
So there isn't much to do here. I might be able to fake a speedup by preloading the next and previous images into a cache. So a touch just displays the appropriate cache image and causes a background read to fill the next or previous cache again. I'll look into what it would take for that.
#5 Updated by Hammel about 1 month ago
- Status changed from New to In Progress
- % Done changed from 0 to 60
I rewrote the code to cache the next and previous images but there is some delay. The biggest problem is that it takes 3 seconds to load the image files from the USB stick. I'll dig around and see if there is anything that can be done to speed reading from the USB stick. Otherwise, this is as much as I can do here.
#6 Updated by Hammel about 1 month ago
Now I'm a little skeptical of this. Here is hdparm output for the USB stick:
- hdparm -tT /dev/sda1
Timing buffer-cache reads: 448 MB in 0.51 seconds = 899050 kB/s
Timing buffered disk reads: 58 MB in 3.01 seconds = 19679 kB/s
I can get 58MB in 3 seconds. The first few images are all a few 100's bytes each. So two (not three, as I said earlier) seconds to load a 200k image into a pixbuf? Plus another second to scale and possibly rotate. There are alternative functions that scale the image when it's read, but since I need to rotate first, the scaling has to be done in a separate step.
An alternative solution might be to cache a large number of files as raw data I pass to gdk_pixbuf_new_from_resource() but I'm not sure if the char *resource argument to that is raw image data or not. Also, I still need to rotate and scale so at best I'm just caching file reads which may save 2 seconds.
I need to dig deeper into GdkPixBuf usage.