So, yes, I can reproduce the issue with the supplied icons. I created 19 test add-ons each using one of the four icons. Plus I have 3 XF add-ons using our standard ~1.2KB icon.
These are the results in seconds of how long
$image->save()
takes for each one:
Code:
2021-06-30 09:43:40 float(0.48349142045851) (Test 1)
2021-06-30 09:43:41 float(0.53236198425293) (Test 10)
2021-06-30 09:43:41 float(0.51950478553772) (Test 11)
2021-06-30 09:43:42 float(0.53217101097107) (Test 12)
2021-06-30 09:43:42 float(0.50297498703003) (Test 13)
2021-06-30 09:43:43 float(0.46560597419739) (Test 14)
2021-06-30 09:43:43 float(0.47917985916138) (Test 15)
2021-06-30 09:43:44 float(0.48830890655518) (Test 16)
2021-06-30 09:43:44 float(0.52034378051758) (Test 17)
2021-06-30 09:43:45 float(0.51168704032898) (Test 18)
2021-06-30 09:43:45 float(0.48771500587463) (Test 19)
2021-06-30 09:43:46 float(0.52005100250244) (Test 2)
2021-06-30 09:43:46 float(0.51728320121765) (Test 3)
2021-06-30 09:43:47 float(0.51793122291565) (Test 4)
2021-06-30 09:43:47 float(0.35379695892334) (Test 5)
2021-06-30 09:43:48 float(0.40026807785034) (Test 6)
2021-06-30 09:43:48 float(0.35393905639648) (Test 7)
2021-06-30 09:43:48 float(0.3932638168335) (Test 8)
2021-06-30 09:43:49 float(0.52607607841492) (Test 9)
2021-06-30 09:43:49 float(0.0027520656585693) (XF)
2021-06-30 09:43:49 float(0.0025899410247803) (XF)
2021-06-30 09:43:49 float(0.00242018699646) (XF)
I then ran the icons through pngquant locally though likely not with the most optimal settings as the icons are still around ~22KB whereas tinypng.com gets them down to about ~12KB:
Code:
2021-06-30 09:48:50 float(0.048039197921753) (Test 1)
2021-06-30 09:48:50 float(0.045054197311401) (Test 10)
2021-06-30 09:48:50 float(0.047561168670654) (Test 11)
2021-06-30 09:48:51 float(0.044196128845215) (Test 12)
2021-06-30 09:48:51 float(0.053647994995117) (Test 13)
2021-06-30 09:48:51 float(0.049530982971191) (Test 14)
2021-06-30 09:48:51 float(0.055483818054199) (Test 15)
2021-06-30 09:48:51 float(0.051875114440918) (Test 16)
2021-06-30 09:48:51 float(0.046474933624268) (Test 17)
2021-06-30 09:48:51 float(0.04341983795166) (Test 18)
2021-06-30 09:48:51 float(0.054211139678955) (Test 19)
2021-06-30 09:48:51 float(0.047724962234497) (Test 2)
2021-06-30 09:48:51 float(0.068761110305786) (Test 3)
2021-06-30 09:48:51 float(0.053205013275146) (Test 4)
2021-06-30 09:48:51 float(0.029088973999023) (Test 5)
2021-06-30 09:48:51 float(0.032469034194946) (Test 6)
2021-06-30 09:48:52 float(0.35818815231323) (Test 7)
2021-06-30 09:48:52 float(0.032851934432983) (Test 8)
2021-06-30 09:48:52 float(0.044275045394897) (Test 9)
2021-06-30 09:48:52 float(0.0024509429931641) (XF)
2021-06-30 09:48:52 float(0.002493143081665) (XF)
2021-06-30 09:48:52 float(0.002593994140625) (XF)
(Note there's an outlier here in that I somehow missed optimising Test 7).
That's quite a big difference.
It's worth noting that the savings would probably be greater. We render these as 64px x 64px. For high DPI displays, providing 128px x 128px images is reasonable. But these are 256px x 256px.
Just to explain in more detail why we use this data URI approach for icons currently and what the approach was originally.
Add-on developers store the icons in a directory that is not typically web accessible. The original approach was we loaded the images from a special URL, e.g.
https://domain.com/admin.php?add-ons/icon/
.
Each one of these requests is a fresh XF request and triggers a database connection. Some hosts were struggling with this, leading to potentially even worse performance than we're seeing here with the scope for hitting hard server limits. The solution was to move to this data URI approach where we read the image data and encode it to a base64 URI and render it inline. Potentially not as good in some ways seeing as that work has to happen on every page load, vs the original approach which may have benefited from some form of caching.
But, since then, we've not had any other reports of slow loading add-on lists.
I accept the approach isn't perfect - we have discussed other approaches in the past - but unoptimised images that are 2-4 times larger than they need to be certainly exacerbates the issue considerably.
Regardless of what we do next, I strongly recommend optimising all of those icons so they're no larger than 128px square and are compressed to a much smaller size (which is generally lossless to the naked eye).
We'll keep this open for now and discuss other options but certainly that's the best workaround we can recommend at this time.