-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Perf] Laggy when scrolling quickly through a list #25
Comments
Making this smooth was one of my top priorities while writing hunter, so this is serious. :) What's your CPU? Did you compile with "cargo --release"? The --release part is really important, since the default debug build doesn't optimize very much and adds a lot of overhead due to overflow checks and such. The debug build easily eats up a full core and them some on my system, but with --release it drops down to 30-40% in the worst case when scrolling with various types of previews being shown and animations on. I've been experimenting with enabling LTO, which reduces this further to around 20% and makes the binary smaller. CPU: i3 5005 2x2Ghz If hunter can't process whatever the key makes it do fast enough, then those build up. I guess it might be possible to flush the input buffer after reading a key, but then it might drop something you actually want.. |
I didn't compile via Processor Name: Intel Core i5 |
No, I think cargo install builds with --release by default, so that should be fine. What about CPU usage? Does it use up all of your CPU during scrolling? Can your terminal keep up? Does it still happen when you zoom in on the main column ("c")? That also disables preview processing completely. If that helps you could try disabling just the animations. (Put "animations=off" in "~/.config/hunter/config". If that fixes it, it means your terminal has problems drawing fast enough. To be fair, hunter's animations are a little bit abusive ;). |
I'm seeing a moderate CPU spike in iTerm when this happens. Main-column zoom in ("c") doesn't appear to have any positive impact. I tried it in Terminal (default MacOS terminal app, as opposed to iTerm) and I saw a CPU spike here as well, though about 30% less, and I wasn't seeing the "inertial over-scroll" happen. I think it's not a "bug" in the sense that anything unexpected is happening (it seems). Likely more to do with perf issues with my terminal combined with the high load of I'll let you decide if that means (The "animations=off" config didn't seem to do anything, still saw animations) |
Oh, you're on macOS! In that case the config file is in
It's what the Apple guidelines say, but for a terminal app it's probably not the best choice. I should change this, but without macOS it's hard to test :). Interesting. I guess that means iTerm is slow :). But I have to admit that the drawing in hunter is not very efficient either. There is a lot of overdraw, especially when it clears a big area, even though there were just a few lines. I guess that could and should be optimized to lower the load on the terminal. I'm also thinking about this dropping of keys in the input buffer. But the problem is that it can't process/draw/whatever and react to your input fast enough. It will still feel laggy, so it's more of a workaround, than a fix. Although that's' probably better than being uncontrollable for a time. |
iTerm certainly isn't the most performant, but it has some nice features :) Thanks for the details, I'll try putting the config there and see what happens. (Update: still doesn't seem to disable animations)
|
I got reports that it's loading the file, but since I don't have access to macOS, I can't really test or debug it myself. I guess I'll try again in a VM some time. I'll probably also add some startup options/flags to disable this soon, that could be used as a workaround in the mean time. |
Ok, so I implemented stdin flushing. Surprisingly, I actually noticed a slight improvement myself. When I checked how big the buffer is I saw that the there sometimes were 1-2 characters buffered up during scrolling, which caused it to slightly overshoot during scrolling. I'm still wondering why that is, maybe the termial doesn't consistently read the keys as fast as the key repeats when it's pressed down. Anyway, that should more or less fix this issue. |
Awesome, thanks for the update. Let me know if there's anything I can do to help with the config thing. |
I pushed a new branch "osx_config". If you could test that it would be great. It should print two messages to stderr when it builds the path to the config file, so it might look a bit messy unless you start it with "2>dbg.txt". It should print the correct path there. If that works, but still doesn't affect what it does, you might see something in the log (press g). Be aware that the config file is loaded asynchronously, so if it's not ready immediately you will see the default config until it's ready, but that's not likely to happen anyway. |
Will have a look soon after the weekend. Cheers :) |
OK, sorry for the wait. I took a look at the source, and I found that I had the config wrong. I had So, with animation off (yes the config_path code is working on macOS), it does speed up significantly. However, the "inertia effect" is still (just) noticeable. It's very minimal, overall much more performant. Any latency with animations off is probably more to do with the ITerm lag. |
Great, then I will merge the osx-config stuff into master soon. Thanks for testing this, it bugged me for a long time. Regarding the inertia, I could try flushing stdin before reading, right now it's flushed after reading a key. But I noticed that this breaks pasting into the minibuffer. I should probably limit the flushing to the browsing only. |
Done. Not sure if it's an improvement though. |
Need to stop flushing in the minibuffer. Different problem though. |
I have similar issues: slow scrolling when I hold down-arrow; though no inertia.
This actually blocks hunter: when I set my keyrepeat slow enough not to get the errors, I end up with much faster scrolling, though still slow. It's a 73G dir with almost 74.000 files and subdirs; In this dir, My normal rate: Some other comparisons, all done in this same dir: load time: memory usage: cpu usage while scrolling: nnn isn't really a fair comparison here, since it doesn't do previews. This is in alacritty, though kitty behaves the same. I have this config:
|
There are some issues with very large directories that I missed initially. The largest directory I tested on had ~3000 files in them so I never noticed. It used to be the case that hunter completely hung up on fsnotify events in huge directories because the update algorithm was inefficient and ran on the main thread, too. Same when selecting 10k files at once and running "rm $s". Complete lockup, due to ineffiecnt string handling in my string library. That one has been fixed completely, but fs updates is still very suboptimal and needs some work. At least it's off the main thread for now. As far as scrolling goes there is a low hanging fruit I'm going to tackle soon. I just need to add a field to the Files struct that stores the amount of files that are shown (depends on hidden file setting, filters, etc.) because right now this is calculated by iterating over ALL files and filtering out what shouldn't be shown. In a flame graph I've seen this takes a substantial amount of time since it's done many times per key press, so that alone should give a nice boost. Loading times can probably be improved a lot, too. Loading a directory happens in stages already (first only names, then metadata (size, ctime, etc), then calculate file count in directories) and at least for previews it only fetches metadata for stuff that's on screen. You might have noticed it in the preview pane. Since rendering updates is now off the main-thread this can probably also be done for the main view without causing stutter. Just to be clear, by loading time you mean the time until the content shows up, not the time hunter takes to load and accept input? EDIT: I just tested nnn again and it's definitely quiet a bit faster to load 100k files. On the other hand it hangs until the directory is loaded, whereas hunter still lets you move out of the directory, even as it is loaded. I think the main advantage of nnn is that it only has to load one directory, whereas hunter has to load 3 at once. If hunter prioritized the main view, so that the other views waited until the main view is done loading it could probably get pretty close. Tested on a HDD atm, so YMMV. |
Ok, so as I thought, keeping the number of visible files around gives a huge boost to performance. It's almost funny. I can now browse a 100k directory without any trouble. A problem that I'm now noticing is that CPU usage goes up more and more the further I scroll down. At the start it's at 20-30%, but at the bottom it goes to around 80%. Still, pretty nice improvement for such a small change. The flame graph looks very clean by now, which is nice, because I can easily remove most those huge bars without too much trouble. |
With the latest update hunter handles directories with 1M (!) files just fine during browsing. CPU usage with 1M files is under 10% at the top and still under 50% at the bottom on my system. That is WITH previews and animations. When I press (c)olumn to zoom in on the main view it's around 4% in a "small" directory of 6K files. Otherwise it tops out at 10% with all the fancy stuff. Quite an amazing improvement and I didn't even change the fundamental algorithms. All this just by caching the number of displayed files in the directory and the currently selected file. Two problems remain: Loading 1M files is quite slow and hunter will easily use up a GB of memory. I'll tackle that next. |
Thank you! You mentioned that the UI shouldn't block when loading a dir. |
That is terrible and shouldn't ever happen when just moving around. One of the main reasons I started writing hunter in the first place was because I hate such lock ups, so to me that's a critical bug. :) Nice catch, will look into it. |
Note, I naively did ```cargo run .`` so I got a dev build. (I'm new to rust, only saw this after I had already posted the above report)
|
Looks like you're missing gstreamer, or at least haven't set it up so that it can be linked in. Unfortunately I'm not familiar with nix, so I can't help you there. But you can try to disable video support by copiling with
Seems to be working as intended now. |
Cool, I can build a release version and the blockage is gone, great! One other perf issue: PS: There was a typo in my comparison: hunter takes 13s to load, not 3. |
The main reason is that hunter precalculates all the formatted lines (with name, color, padding, size, etc.) in a directory before it draws anything, which is quite suboptimal and also the reason it's using so much memory. This was supposed to be an optimization, but with large directories it's clearly counterproductive. Nevertheless, I worked out some additional major speedups in the last two days and on my machine a directory with 500k files shows up in about ~4 seconds, which I think is quite reasonable already, although I can see that it would be annoying to wait that long every time. I never thought about testing such gigantic directories before and thus hunter hasn't been optimized for them yet. Although with the huge progress in the last few days and no end in sight I'm starting to think that it might become faster than anything else at some point, or at least very competitive. |
Thank you!! |
Nah, I'm not quite done yet, I think I can shave off another 80% or so with a tiny bit of tweaking. ;) Glad to hear it's working great for you now. |
Alright, I pushed another couple of huge speedups. It's about as fast as it can get now. The only way to make it faster is to thoroughly redesign some internals, asynchronous prefetching and maybe caching more stuff. It's seriously FAST now. The bottleneck is the overhaed from the readdir syscall, which is pretty slow (has to pointer chase a linked list, which takes some time with 500k files). Still, it loads 500k files in under 2 seconds now. I'm going to make it even faster eventually, but for now this is as good as it can get. If anyone still has problems feel free to reopen. |
As lightning! ⚡ |
If you scroll fast (e.g. continually depress the down-arrow to move the cursor down a list), input becomes "laggy" and doesn't stop as soon as input stops.
Expected: cursor should stop immediately when the key is released
Actual: when you release the key the cursor continues for a few extra lines. The longer the key was held, the further "extra distance" the cursor goes, thus giving it an "inertial" effect.
The text was updated successfully, but these errors were encountered: