Filesearcher: add search in book metadata#10198
Conversation
|
If the overhead isn't simply in the "get metadata" step, but in the "parsing metadata" one, you might want to restrict the search to very specific fields (e.g., title/author/series). I can certainly see the appeal of including description in there, but that might very well be your bottleneck right there... ;o). Sidebar: This is nearly instantaneous if done via the calibre plugin/metadata ;p. |
|
Description in fb2 books from Flibusta contains important information like translators, publushers etc. |
If it actually helps the performance and doesn't look too messy, yeah? |
|
I don't think that 1 or 4 metadata fields lookup would change anything (and neither html2plaintext) - the bottleneck is opening each book. |
|
Isn't that info in the SQLite DB? |
|
If the coverbrowser plugin is enabled, it may be, for directories browsed - and it may not for sub/directories not visited or not "Extract and cache book information", or recently added books. About the coverbrowser sqlite db, I'd like to mention that if we were to need a proper sqlite database for the purpose of metadata search, or a "library view" (ala Nickel, that some users would prefer to our file browser), I would prefer it to be another sqlite database. It could be a new plugin that could duplicate and extend bookinfomanager.lua if needs be. (Or such a DB should be a "core" service, that coverbrowser could be a client to - but then, KOReader would no longer be the KOReader I like :) |
|
For me the metadata is fine as is. :) |
|
Search results view is now consistent with the file browser view (sorting, filtering, classic display mode). FileChooser change: in classic mode files mandatory now shows the parameter by which sorting is done. Minor wordings changes of the file searcher dialog window: |
|
Fine with the switch of tap/long-press in the results. |
|
Not a benchmark but rough estimation (a folder with 5 epubs of about 2 MB each): searching in metadata of an unopened book is ~50 times slower comparing to an opened one (with sdr). |
|
Various thoughts: You could add a small wrapper around BookInfoManager:getBookInfo(filepath) in coverbrowser's main.lua, so you could use You could also force this extraction for each book - although that might be complicated and ugly (it's done in a background subprocess asynchronously, and it usually fetches the cover with the expected size for the current coverbrowser view). Or you could even not rely on coverbrowser, and just cache (dump()/load()) a big table with all the metadata you have extracted once - so it is "slow" only the first time it is used, and when new files are met. Also, I haven't look at all the code, but I guess this is blocking: if you have 300 never opened book, KOReader will go at opening the 300 of them, and the user can't stop that - and he may get stuck for 15mn... |
And if you would do that, it could be a core module, just caching filepath/filetimestamp/{metadata}, that you could just complete and iterate. May be you could even use LuaData to add new item to it, like we do for dict lookup queries. |
…nection Due to <koreader#10198 (comment)> I browsed the SQLite documentation a bit. Looking at <https://www.sqlite.org/pragma.html#pragma_optimize>, it says: > To achieve the best long-term query performance without the need to do a detailed engineering analysis of the application schema and SQL, it is recommended that applications run "PRAGMA optimize" (with no arguments) just before closing each database connection. Long-running applications might also benefit from setting a timer to run "PRAGMA optimize" every few hours. > > This pragma is usually a no-op or nearly so and is very fast. However if SQLite feels that performing database optimizations (such as running ANALYZE or creating new indexes) will improve the performance of future queries, then some database I/O may be done. Applications that want to limit the amount of work performed can set a timer that will invoke sqlite3_interrupt() if the pragma goes on for too long. Or, since SQLite 3.32.0, the application can use PRAGMA analysis_limit=N for some small value of N (a few hundred or a few thousand) to limit the depth of analyze.
|
Thank you. (At a first glance I tend to extending the DocSettings module to maintain the new DocPropsCache that would be a new file with hashes [filepath] = {book_props}. It would be updated within |
Dunno, the current state could block the user for 15 minutes with no way to get out but by powering off, so it feels like a non-feature :/ (unless he looks in a small subtree, or is used to opening all his books).
Feels like the simpler solution, a "cache in the middle" :)
Well, I wouldn't want that big cache file to be rewritten each time I switch books, so you'd have to look if metadata has changed to see if it really need updates.
Yep, and I was happy not having to think about it until you came up with this PR :/ :)
Anyway, lots of thinking to give it - and not really happy about having to give it that much :) |
|
I agree with the above. I'm not motivated to create something like a library view, but if you're implementing something along these lines I don't think it's a very good idea unless you take CoverBrowser as a point of departure and add some well considered extra columns. |
But if you want to keep that (and may be this will be enough, and we can postpone that dreadful thinking :), you could:
|
Yeah, that sounds sensible. You can't call (I'll look at the logs tonight to confirm, but that's probably it). EDIT: Yup, definitely that ;). |
|
I've made a simple benchmark to compare the speed of getting book props from sdr vs coverbrowser sql. |
|
You mean in the specific scenario of search while in classic mode? Yes, I think it would make sense to say that completely classic search for metadata doesn't make much sense. Btw, where'd your run the benchmark? If that was on the emulator then |
|
I ran the benchmark on my Kindle Voyage. I mean using the coverbrowser sql base in the file popup menu in FM, History and Favorites: koreader/frontend/apps/filemanager/filemanager.lua Lines 311 to 318 in b3fe90c koreader/frontend/apps/filemanager/filemanager.lua Lines 329 to 336 in b3fe90c Currently in classic mode it reads book props from sdr. I propose at first to try sql, then to try sdr, and then to open a file to get props. |
I suppose? In that case the difference seems immaterial; it feels instantaneous either way. Are you talking about when there's no metadata.lua yet? It seems hard to imagine it'd be 9 times slower? |
|
Yes, the difference is not visible per one file. |
|
What does your benchmark consist of exactly? I find it hard to imagine that simply parsing a tiny bit of Lua is not only heavier than instantiating all of SQLite but an order of magnitude so. But I have heard that the filesystem on Kindle is unbelievably slow… |
|
It was a previously opened book with metadata extracted to sql. logger.info("doc_settings start", os.clock())
for i = 1, 1000 do
local doc_settings = DocSettings:open(item.path)
local descr = doc_settings:readSetting("doc_props").description
end
logger.info("doc_settings end", os.clock())
logger.info("bookinfo start", os.clock())
for i = 1, 1000 do
local bookinfo = self._manager.ui.coverbrowser:getBookInfo(item.path)
local descr = bookinfo.description
end
logger.info("bookinfo end", os.clock())
|
|
The saner way to do this is via koreader/frontend/document/credocument.lua Lines 779 to 783 in b3fe90c |
|
I don't see such a drastic difference, closer to twice as slow. According to the profiler up to about 25% of the difference comes from getHistoryPath, basename and buildCandidates, but without doing anything about that the benchmark comes to the same result if you limit the metadata to basically just metadata, along these lines (see #2789): -- we can read Lua syntax here!
return {
["doc_pages"] = 250,
["doc_path"] = "/home/frans/src/kobo/koreader/test/juliet.epub",
["doc_props"] = {
["authors"] = "William Shakespeare",
["description"] = "Romeo and Juliet is a tragic play written early in the career of William Shakespeare about two teenage \"star-cross'd lovers\" whose untimely deaths ultimately unite their feuding households. It was among Shakespeare's most popular plays during his lifetime and, along with Hamlet, is one of his most frequently performed plays. Today, the title characters are regarded as archetypal \"young lovers\". (From Wikipedia)",
["keywords"] = "Fiction\
Drama\
Romance",
["language"] = "en",
["series"] = "",
["title"] = "Romeo and Juliet",
},
}But I don't know why you'd make things complicated for something that isn't slow and that you only do irregularly. PS For fun you can throw a closeDbConnection() in there and watch the time increase by an order of magnitude over the plain file method. I suspect that that's more realistic, at least for my usage. Unless you keep it open even when switching between reader and filemanager. |
|
So, the summary of changes in this PR: (1) Search files (2) File sorting Works good I hope. |
| if DocumentRegistry:hasProvider(item.path) then | ||
| UIManager:scheduleIn(0.5, function() |
There was a problem hiding this comment.
Worth a comment - so we remember that and may be one day find a better solution to it.
-- Workaround an issue with this long-press' release being handled as tap by the Reader we launch
There was a problem hiding this comment.
Actually not a good workaround, if a long-press is longer than 0.5 sec it doesn't help.
There was a problem hiding this comment.
Not good, but good enough ? :) Let's not block this PR, we can fix that later if we get a better idea.
Another idea (dunno if it is good).
--- a/frontend/ui/widget/menu.lua
+++ b/frontend/ui/widget/menu.lua
@@ -131,7 +131,7 @@ function MenuItem:init()
},
HoldSelect = {
GestureRange:new{
- ges = "hold",
+ ges = self.handle_hold_on_hold_release and "hold_release" or "hold",
range = self.dimen,
},
},and provide and pass handle_hold_on_hold_release when you know it's best to handle it that way.
I think we mostly everywhere handle long-press before the finger lift - but we have a few places (don't really remember where) where we handle it on finger lift (so, hold_release), probably for good reasons. I remember I had sometimes been surprised by that (waiting, and seeing nothing done, until I lift my finger), and it's a bit inconsistent, but well, it's just fine.
|
The changes to FileChooser in this PR have broken the unreadable dir content handling (like going up from Android |
|
I can simulate that on the linux emulator with Hope this helps :) |
| local start_with = G_reader_settings:readSetting("start_with") | ||
| for i, v in ipairs(start_withs) do | ||
| if v[2] == start_with then | ||
| return T(_("Start with: %1"), v[1]) |
There was a problem hiding this comment.
A default is missing. Cf. #10368.
The old one said:
local start_with_setting = G_reader_settings:readSetting("start_with") or "filemanager"Regression from koreader#10198. Fixes koreader#10368.
KOReader 2023.04 "Solar Panel"  It's been another busy month squashing many bugs. Our Mac users will be happy to hear that I told macOS we've supported HiDPI since long before anyone came up with such terminology (koreader#10341), and that the program can now natively build on M1 devices (koreader#10291). Solar panel credit: <https://openclipart.org/detail/294030/solar-energy> by gnokii We'd like to thank all contributors for their efforts. Some highlights since the previous release include: * Readerzooming: fix use of default settings (koreader#10205) @hius07 * ButtonDialog/ButtonDialogTitle: consistent 'width' handling (koreader#10230) @poire-z * MovableContainer: add support for anchoring initial position (koreader#10230) @poire-z * Book map, Page browser: add top left menu (koreader#10230) @poire-z * Book style tweak: add button with CSS suggestions (koreader#10230) @poire-z * crengine: fix parsing of multibytes encodings (koreader#10230) @poire-z * readerstyletweak: update profiles on unregistering in dispatcher (koreader#10247) @hius07 * Filesearcher: add search in book metadata (koreader#10198) @hius07 * Fix: Updated legacy directory, which crashed the program (koreader#10260) @Mochitto * ReaderLink: allow a forward location stack (koreader#10228) @yparitcher * BookInfo: add page information (koreader#10255) @hius07 * Center pdf manual zoom mode (koreader#10246) @nairyosangha * File browser: add Folder Menu (koreader#10275) @hius07 * Calendar view: add options to change start time of days (koreader#10254) @weijiuqiao * filechooser: fix crash on "unreadable content" (koreader#10283) @hius07 * Sync book statistics: add to dispatcher (koreader#10285) @ptrm * [plugin] Exporter: use util.getSafeFilename() to remove illegal characters from output filename (koreader#10282) @Mochitto * readerbookmark: fix writing pdf annotation (koreader#10287) @hius07 * Folder Menu: sign for Home folder (koreader#10288) @hius07 * ListMenu: show mark for books with highlights (koreader#10276) @hius07 * Calendar view's day view: thicker separator at 00:00 (koreader#10289) @poire-z * PageBrowser: tweak scrolling behaviour at book start/end (koreader#10289) @poire-z * Make `kodev check` feature complete (koreader#8682) @yparitcher * macOS: support for M1 building (koreader#10291) @ptrm * Reader: do not apply font size and spacing out of range (koreader#10295, koreader#10307) @hius07 * File browser: show Folder Menu on long-press on Home icon (koreader#10298) @hius07 * SSH.koplugin: fix cant stop SSH server bug when pid file's stale (koreader#10300) @weijiuqiao * PM: Optimize task queue handling around standby (koreader#10203) @zwim * statistic.koplugin: fix today's timeline showing next day when within custom offset (koreader#10299) @weijiuqiao * ReaderThumbnails: update cached page thumbnail on bookmark note change (koreader#10303) @hius07 * SDL: add multitouch support (koreader#10334) @Frenzie * SDL: add HiDPI support (koreader#10341) @Frenzie * BookInfo: fix crash on show cover (koreader#10315) @hius07 * Deal with table.pack corner-cases properly (koreader#10350) @NiLuJe * Android: add Tagus Gea support (<koreader/android-luajit-launcher#412>) @Alfedi [Full changelog](koreader/koreader@v2023.03...v2023.04) — [closed milestone issues](https://github.com/koreader/koreader/milestone/63?closed=1) --- Installation instructions: [Android](https://github.com/koreader/koreader/wiki/Installation-on-Android-devices) • [Cervantes](https://github.com/koreader/koreader/wiki/Installation-on-BQ-devices) • [ChromeOS](https://github.com/koreader/koreader/wiki/Installation-on-Chromebook-devices) • [Kindle](https://github.com/koreader/koreader/wiki/Installation-on-Kindle-devices) • [Kobo](https://github.com/koreader/koreader/wiki/Installation-on-Kobo-devices) • [PocketBook](https://github.com/koreader/koreader/wiki/Installation-on-PocketBook-devices) • [ReMarkable](https://github.com/koreader/koreader/wiki/Installation-on-ReMarkable) • [Desktop Linux](https://github.com/koreader/koreader/wiki/Installation-on-desktop-linux) • [MacOS](https://github.com/koreader/koreader/wiki/Installation-on-MacOS)
…up (koreader#10369) Regression from koreader#10198. Fixes koreader#10368.


Unfortunately it is really slow.
This change is