-
knuxify authored
This is another pretty huge optimization, both memory-wise (in theory - I haven't compared...), but especially speed-wise. To explain this change, let's talk about Ear Tag's previous handling of covers. Historically, Ear Tag supported only front covers, and they were loaded from a path. The reason for that is that we were using a Gtk.Image and loading an image from, well, the path. It occured to me later that this was extremely inefficient - every time we selected a file, we'd have to reload the cover from the disk, causing massive lag. So I optimized it to create two pixbufs - a 48x48 thumbnail and a 196x196 image for the button - and keep them in a helper cover class, then use them for showing covers. Still, though, the system had a couple of flaws: - It still assumed that there was an actual *file* with the cover, meaning that covers extracted from metadata had to be saved as tempfiles. - Based on this assumption, the diffing algorithm (used to determine whether to show a placeholder or the cover when selecting multiple files) was implemented byrunning a file comparison. This meant that we were doing blocking IO operations every time a comparison was done, which was... a lot. - Every time the cover was loaded, new pixbufs were created, even if the cover was bit-for-bit identical with one from another file (as is often the case with albums). The new implementation resolves to change all of this. - All cover data is now stored in-memory. This means no more tempfiles for loaded covers, and no IO operations (past the initial load in the case of covers opened from files)! - A new diffing algorithm was introduced, using xxhash's XXH3 hash to calculate the hash of the data. Compared to more conventional algorithms like SHA256, XXH3 algorithm is super fast and specifically done for file comparisons (where the priority isn't being cryptographically secure, so some computational load can be dropped - citation needed, I'm not a cryptographer). - Moreover, since we now have a hash of the data, we use it to cache cover objects and return an existing object if we detect that the image is bit-for-bit identical. Cover data gets freed once all references to the cover object are freed. Thus, we don't waste memory on repeated pixbufs \o/ - The cover object also stores some metadata about the image (...rather, currently just the mimetype), which backend implementations can use for their own purposes. - As a nice bonus, cover loading is now done fully asynchronously, even from files! This fixes some of the stutter that happened at startup.
knuxify authoredThis is another pretty huge optimization, both memory-wise (in theory - I haven't compared...), but especially speed-wise. To explain this change, let's talk about Ear Tag's previous handling of covers. Historically, Ear Tag supported only front covers, and they were loaded from a path. The reason for that is that we were using a Gtk.Image and loading an image from, well, the path. It occured to me later that this was extremely inefficient - every time we selected a file, we'd have to reload the cover from the disk, causing massive lag. So I optimized it to create two pixbufs - a 48x48 thumbnail and a 196x196 image for the button - and keep them in a helper cover class, then use them for showing covers. Still, though, the system had a couple of flaws: - It still assumed that there was an actual *file* with the cover, meaning that covers extracted from metadata had to be saved as tempfiles. - Based on this assumption, the diffing algorithm (used to determine whether to show a placeholder or the cover when selecting multiple files) was implemented byrunning a file comparison. This meant that we were doing blocking IO operations every time a comparison was done, which was... a lot. - Every time the cover was loaded, new pixbufs were created, even if the cover was bit-for-bit identical with one from another file (as is often the case with albums). The new implementation resolves to change all of this. - All cover data is now stored in-memory. This means no more tempfiles for loaded covers, and no IO operations (past the initial load in the case of covers opened from files)! - A new diffing algorithm was introduced, using xxhash's XXH3 hash to calculate the hash of the data. Compared to more conventional algorithms like SHA256, XXH3 algorithm is super fast and specifically done for file comparisons (where the priority isn't being cryptographically secure, so some computational load can be dropped - citation needed, I'm not a cryptographer). - Moreover, since we now have a hash of the data, we use it to cache cover objects and return an existing object if we detect that the image is bit-for-bit identical. Cover data gets freed once all references to the cover object are freed. Thus, we don't waste memory on repeated pixbufs \o/ - The cover object also stores some metadata about the image (...rather, currently just the mimetype), which backend implementations can use for their own purposes. - As a nice bonus, cover loading is now done fully asynchronously, even from files! This fixes some of the stutter that happened at startup.
Loading