Steps to reproduce:
I've been getting frequent temporary beachballs, sometimes over 10 seconds long, while using Orion.
Using Instruments and Frida I've narrowed down the path where this happens:
- Some function on the main thread posts the notification
FaviconDidUpdate
. - This calls
BookmarksBarItem.iconUpdated
(synchronously on the same thread). - One of the functions called from this eventually executes a SQLite query of the form:
(whereSELECT ICON_HASH FROM ( SELECT favicon.ICON_HASH, REPLACE(REPLACE(REPLACE(favicon.PAGE_URL, 'www.', ''), 'http://', ''), 'https://', '') as _PAGE_URL FROM favicon LEFT JOIN icon_info ON icon_info.HASH = favicon.ICON_HASH WHERE (_PAGE_URL = 'xxx' OR _PAGE_URL = 'xxx/') AND icon_info.ICON_TYPE = 0 AND icon_info.WIDTH >= 0 ORDER BY icon_info.WIDTH DESC )
xxx
is a webpage URL, either from my bookmarks or one that I'm currently visiting.) - This query does a linear scan over all rows of the
favicon
table, which for me has 27,768 rows. - Most of the time the query takes around 33ms, but sometimes it takes orders of magnitude longer, up to multiple seconds. I am honestly baffled at this discrepancy, given that it's scanning over the same data. You would think that this would indicate the thread waiting for a lock or not being scheduled or paging from swap, but Instruments suggests that the thread is actively running and spending most of its time taken in
replaceFunc
, which is a function in libsqlite3.dylib that implements theREPLACE
SQL function. Yet I verified that it calls thereplaceFunc
the same number of times with the same arguments. (And regarding swap specifically, my system has enough memory that it currently shows 0 bytes of swap used, even though I reproduced beachballs recently.) Could it have something to do with P-cores versus E-cores?
Suggestions:
- Cache the
REPLACE
output in a different SQL column and add an index for that column, so that you can query for a specific URL without doing a linear scan over all rows in the table. - Have the notification handler dispatch the work to a background queue, so that the SQL query doesn't block the main thread even if it is slow.
Orion, OS version; hardware type:
Orion Version 0.99.123.1-beta (WebKit 615.1.16.1)
MacBook Pro (macOS Ventura 13.1 build 22C65)