lwouis / alt-tab-macos

Windows alt-tab on macOS
https://alt-tab-macos.netlify.app
GNU General Public License v3.0
10.63k stars 323 forks source link

AltTab is slow to appear when many windows are open #171

Closed mfn closed 4 years ago

mfn commented 4 years ago

Using Version 3.1.0 on 10.15.3 (19D76) using a MacBook Pro (15-inch, 2018) 2,9 GHz 6-Core Intel Core i9.

On my endeavor to mimic the HyperSwitch behavior, I set the "Apparition delay" to 0.

Yet it has a noticeable delay before showing me the grid of application. Not just the first time, all the time.

I've HyperSwitch running next to it and, comparatively, it comes up instantly.

In my super-scientific-not-really benchmarking, I would say the delay is about 250-300ms.

How did I came to this number? Apparently, HyperSwitch also has a way to change the delay, it's called "Delay activation for" I've set it to 0. I increased it gradually until I felt the delay matched that of AltTab 🤷‍♀️

I've searched existing issues:

Thanks

Debug profile:

lwouis commented 4 years ago

Thank you for sharing this feedback! By the way, there is a "send feedback" menu if you click on the menubar item.

image

It creates a form that will basically open a github issue for you. It is very handy for performance issue as it will attach a debug profile of your machine, similar to what you intuitively listed at the top of your message, but more detailed.

image

I think you may want to just put random text and submit it, just to grab the profile from the newly made ticket and paste it here. I would then clean the new ticket so only this one here exists.

Another thing to help investigate this issue would be to use Instruments on the app. It's more involved of course, but that would be way more helpful as we would have hard data to understand where time is spent on your system. On my system everything is instant for instance. You could just run the app with instruments and save the Time Profiler report file as an attachment in this ticket.

Lastly, a simple context questions:

I'm trying to imagine the amount of work needed to display the thumbnails in your case.

mfn commented 4 years ago

Thank you for sharing this feedback! By the way, there is a "send feedback" menu if you click on the menubar item.

Meh, thanks 😄 Wouldn't occur to me that this is an github template, thx 👍

Btw, I believe it doesn't work. I was prompted with a textarea like entry and when I hit "Send", nothing happened but AltTab also disappeared from the menubar 🤷‍♀️

Do you have external monitors? What's their resolution? Are they high dpi?

No, didn't use any external monitors at all for these tests.

Do you have lots of windows open?

With HyperSwitch I count 13, with AltTab 16. Seems that AltTab does not hide hidden/minimized application.

Another thing to help investigate this issue would be to use Instruments on the app.

Not sure .. is this ? First hit of https://www.google.com/search?hl=en&q=osx%20instruments => https://en.wikipedia.org/wiki/Instruments_(software)

Means I need xcode from app store for this, right?

Thanks!

lwouis commented 4 years ago

@mfn thanks for finding out that the feedback form was crashing the app on submit! I released a fix for that. Could you try to submit using the new version? You can update AltTab by clicking there:

image

You should see the new version 3.1.2 I just released. That one should let you send feedback, with the useful debug profile.

Not sure .. is this ? First hit of https://www.google.com/search?hl=en&q=osx%20instruments => https://en.wikipedia.org/wiki/Instruments_(software)

Means I need xcode from app store for this, right?

It seems you're unfamiliar with the XCode ecosystem. I think it's going to be a bit too tricky for you to investigate the issue then. If you want to invest the time and learn, I'll give you some pointers:

Download and install XCode, Apple official IDE. It is (almost) the only way to work on macOS software. In a terminal, run pod install first, to bring dependencies this project uses. Then you can open this project in XCode by double-clicking the alt-tab-macos.xcworkspace file. Then you can click here to start profiling using Instruments:

image

You may need a lot of learning and OS knowledge. If you don't feel like investing time, then just update to 3.1.2 and submit the feedback form to help us see what's unique about your system that's triggering poor performance in alt-tab ;)

lwouis commented 4 years ago

I opened 25 windows on my retina screen, and indeed alt-tab pops up after a few milliseconds. I think i would be hard to shave even more time than what we are currently doing.

The way HyperSwitch is faster is because they show you old thumbnails they cached. They show you incorrect information basically, then they refresh the thumbnails on a schedule every few seconds.

mfn commented 4 years ago

The way HyperSwitch is faster is because they show you old thumbnails they cached. They show you incorrect information basically, then they refresh the thumbnails on a schedule every few seconds.

Well, basically this is the answer, isn't it? :smile:

I commented on this in https://github.com/lwouis/alt-tab-macos/issues/45#issuecomment-544264454 but I'm not sure what was the actual decision not to consider the caching.

You immediate answer in https://github.com/lwouis/alt-tab-macos/issues/45#issuecomment-544302838

I think there is no need to compromise by caching.

🤷‍♀️

From my user perspective:

I can only tell that this works really well for me with HyperSwitch but makes it not possible for me to use AltTab sadly

It seems you're unfamiliar with the XCode ecosystem. I think it's going to be a bit too tricky for you to investigate the issue then. If you want to invest the time and learn, I'll give you some pointers:

Yeah totally, never did anything with it.

run pod install first, to bring dependencies this project uses

~ $ pod
bash: pod: command not found

😢

But I figured it's this cocoapod, so sudo gem install cocoapods did it 👍

Btw, is it updated the lockfile:

diff --git a/Podfile.lock b/Podfile.lock
index 1e903bb..4604eb4 100644
--- a/Podfile.lock
+++ b/Podfile.lock
@@ -17,4 +17,4 @@ SPEC CHECKSUMS:

 PODFILE CHECKSUM: 465451026269525f0f1d2dc7053cf0b789a35421

-COCOAPODS: 1.8.4
+COCOAPODS: 1.9.1

Tried to run this profiler, but: image

Also the regular Build didn't work: image

But given what you said, I guess for this purpose it doesn't make sense to continue down this pat anyway as you already pinpointed the difference in behaviour.

Not sure were this leaves this issue. Are you open to consider the caching approach?

lwouis commented 4 years ago

Also the regular Build didn't work

You're close to being able to running it locally. You are missing one step that is running scripts/generate_selfsigned_codesign_certificate.sh. I should I referred you to the contribution docs where it is explained.

Not sure were this leaves this issue. Are you open to consider the caching approach?

Overall, I think if we introduce caching, then we need a proper ticket to explain details about the UX, and things like refresh frequency and other specs. Please have a look at prior discussion where I highlight issues I perceive with caching:

If we don't introduce caching, but still want better performance, then I don't know if a ticket is a good supporting material as performance is a never-ending endeavor. We can always be faster, and what is currently fast enough for someone is not for another person. I want to avoid a never-closing ticket where we track performance. I do want to improve performance as much as possible though. Not sure how to achieve that best though. We are reaching a point where we need low-level experts now that can understand interaction with the GPU and the OS. I tried my best, but I don't have 10 years of experience doing C or C++ so my best is limited.

What do you think?

mfn commented 4 years ago

What do you think?

Honestly?

Despite all the feedback you gave regarding caching / showing wrong information: I still think it's the way to solve the problem that some (obviously not you) experience a delay they cannot "configure away" 🤷‍♀️

lwouis commented 4 years ago

How about the UI? Would you communicate the fact that the thumbnails are stale to the user with some UI language? (e.g. adding a spinner somewhere on the window until all thumbnails are fresh, dimming a bit the stale thumbnails, marking them with some icon or text if they are stale, etc). Or do you think it's okay to not communicate that info?

I actually think it would be pretty easy to implement caching. Today there is a function to refresh all thumbnails on shortcut press. It may be as easy as calling that function on a timer, then on shortcut press show the UI then call it once more, or even do like HyperSwitch and not even trigger a refresh on shortcut, but just wait for the timer to trigger the next refresh.

To enable caching, there would be a checkbox in the preferences panel "Cache thumbnails for more responsiveness" with a slider to decide the frequency. Something between 1 and 5s maybe?

I'm worried about these background refreshes using the computer resources a lot, especially the battery on unplugged laptops. I wonder if HyperSwitch has a considerable impact on battery life with its continuous background work

mfn commented 4 years ago

How about the UI? Would you communicate the fact that the thumbnails are stale to the user with some UI language?

It's a valid question.

HyperSwitch just went ahead, implemented caching and, to me knowledge, there's no UI info about it.

HyperSwitch also (again, to my knowledge) doesn't have a dedicated public forum or something, so there's hardy any info / user feedback how users of it perceive it.

I guess they just a) don't care b) cope with it c) chose another tool.

To enable caching, there would be a checkbox in the preferences panel "Cache thumbnails for more responsiveness" with a slider to decide the frequency. Something between 1 and 5s maybe?

Why would there need to be a frequency? Sounds more complex than just chaching.

When I enable caching I will have these two expectations (based on our dialog here):

  1. thumbnails show up as instantly as they can be when I invoke AltTab
  2. in the background a refresh of the thumbs is triggered
    • once it's done doing that, it updates the thumbs in the cache
      • whether this updates the screen UI too depends on whether AltTab is still invoked (as in: the thumbnail is still shown) or not

I'm worried about these background refreshes

If they would be continuously (i.e. frequency) I would be too but I don't follow where this comes from.

thanks!

lwouis commented 4 years ago

If they would be continuously (i.e. frequency) I would be too but I don't follow where this comes from.

I thought HS used a scheduled refresh! I just tested, and it refreshes the thumbnails after a few seconds after you interact with the app. This includes invoking the UI, but also just moving the selected thumbnail left/right triggers it, which is why I assumed in the past that there was a scheduled refresh.

Ok so if there is no periodic re-cache, it means that the thumbnails can get really stale.

I'm fine with adding cache as a preference. Like I said I think the implementation may be trivial. Feel free to open a PR if you want this fast. The current next milestone is focusing on keyboard shortcuts issues.

lwouis commented 4 years ago

I experimented with some kind of basic caching. Here is the branch where the logic is: show the UI, then update the thumbnails and refresh the UI.

I noticed some interesting things.

The UI still has some ms of latency before it shows in high load situation. I simulate high load by having 63 windows open on my retina display. That's a lot of pixels to push on screen (each thumbnail is a full high dpi image, downscaled, which takes memory and cpu/gpu).

Because it's slow to simply display the cached content, I wondered "is this poor implementation of our NSCollectionView, or is there another limiting factor like the image being downscaled from CPU instead of GPU, or memory recopies from GPU mem to CPU mem. To help shed some light, I launched HyperSwitch to see if they perform fast. If they do, then there is something that we are doing wrong, or not doing.

HS only shows 27 thumbnails in this scenario for some reason. 5 x 5 + 2 offscreen at the bottom. It means it's hard to compare because if I only keep 27 windows, suddently AltTab performs quickly too. Not as quickly, but almost instant too.

Conclusions: caching may be the wrong target here. I think there may be a perf bottleneck with either layout. Only measuring/profiling will reveal where time is actually spent. I did a whole bunch of that already however, and it's extremely hard to find the bottleneck lots of computation is not done in our threads, but on the OS threads. Also the profiling is not showing memory recopy, gpu vs cpu rendering of NSView, layer caches, buffering, etc, which is where I think the bottleneck is.

lwouis commented 4 years ago

I used Instruments to profile while having hundreds of windows open. I see the following:

image

All the _dispatch_worker_thread2 threads are because when querying all window screenshots, we do it in a multithreaded pool. So all these 1-4ms calls for screenshots are parallel. Very nice.

We see all the latency is coming from Main Thread taking ~200ms. On the right you see where most of the time is spent:

image

The first is 112ms spent on layout:

image

The second is internal CALayer rendering:

image

This confirms my suspicion that it's not so much about caching the pictures as it's actually quite fast to retrieve them all (I know this because I tried to retrieve them 60 times a second in the past to have them be live/video). The issue is with layouting the view.

I think the layout code is pretty poor and can greatly be enhanced. The main issue I believe is in this function. Especially the invalidateLayout and layoutSubtreeIfNeeded calls.

lwouis commented 4 years ago

I pushed code in the cache branch that shows the previous view instantly, then re-layouts. It looks pretty janky but has no latency.

@mfn could you please test it and tell me if you would prefer that experience to the current one? I'll attach a build here for your convenience: AltTab.app.zip

This illustrates that is it possible to have no latency with fresh images being fetched, but that the issue is layout performance. There are many ways to go about optimizing layout:

Update: another option I forgot would be to use a third-party OSS library to replace NSCollectionView.

mfn commented 4 years ago

Oh wow, the performance is like day and night!

WOW, really!

could you please test it and tell me if you would prefer that experience to the current one?

That's a big 👍

mfn commented 4 years ago

One drawback I noticed is: every time switching to a new window, it now appears instantly but after a few ms it shuffles the recently switches windows in to their (I suppose chronological?) place, which is visible and distracting.

Hard to explain 😄

mfn commented 4 years ago

I'm finally able to use it daily. I just never could because of this latency.

I'm so grateful you did bear with my on this matter!

(Now I can also give more feedback finally 😏 )

lwouis commented 4 years ago

I worked deeper on this. It's such a complex problem. I've noticed that HyperSwitch has many limitations:

A general thing about caching:

@mfn note that the version you're using has many issues with corner cases I think. In other words, it's easy to make the app seem fast if you break functionality with some use-cases. Like I don't use the setting to pop the UI on the screen including the mouse, but we have it in AltTab, and if you use that, or have apps open while AltTab is open, or other complex use-cases, I'm sure you will start seeing problems.

I think the way forward is about small optimizations to scrap off a few dozen ms, or complete rewrite to leave NSCollectionView and go with a custom NSView with our custom logic.

lwouis commented 4 years ago

Very interesting discussion here for a similar issues where people discuss AppKit as layer on top of OpenGL/Metal and that either you tune AppKit but it's very hard cause poor documentation, or you just draw it yourself in OpenGL/Metal then you have understanding.

I found especially interesting to learn that WindowServer is doing the rendering work which explains why i don't see rendering in the profiler in Instruments. Something like 20-50ms is spent on AltTab threads, yet i feel it's taking more frames that than to display e2e.

I'll also look into finding ways to measure how many frames it takes to render the window in a more scientific way. I found this tool but there may be better ways like recording the display and keyboard with my iphone slow-mo camera and just counting the frames. But even then, the OS is probably generating lag on it's own so i need to compare to a baseline fast app like maybe typing a character in the terminal? Anyway lots to study here

lwouis commented 4 years ago

@mfn I tried hard to make it work for a few days before realizing that NSCollectionView is not a good pick for the UI if I want to have any chance to optimize performance. I rewrote the logic using a custom view. Could you tell me if it performs better on your system? Not that the UI will be up-to-date as soon as it shows (no more async update of the thumbnails). Here is a build for convenience: AltTab.app.zip

Here are some comparison of master vs the new branch:

New branch, first and second launch Screen Shot 2020-03-24 at 16 06 37 Screen Shot 2020-03-24 at 16 07 58

Master branch, first and second launch Screen Shot 2020-03-24 at 16 08 07 Screen Shot 2020-03-24 at 16 06 29

lwouis commented 4 years ago

Note for history: I also experimented with drawsAsynchronously but didn't see any difference in performance while profiling.

mfn commented 4 years ago

Performance is absolutely great now, many thanks!

lwouis commented 4 years ago

Not much can be improved on the drawing side. Currently the bottleneck is asking the OS for windows images. Drawing takes very little time, 15ms for example on my system with around 50 windows open on my retina display (retina means ~500kB for each image). Basically we miss 1 frame.

However, when I added measurement time around the OS API calls, I see ~200ms. This feels in line to what I observe in the end-to-end experience.

The OS API calls are completely multi-threaded currently, so the only way I can imagine to reduce latency of showing the app, is to show cached images then refresh thumbnails asynchronously afterwards.

I made a POC on this branch: https://github.com/lwouis/alt-tab-macos/tree/async-thumbnails

With macOS multi-threading model, there are a number of loops to jump through to achieve this. Especially I faced issues with refreshing the thumbnails asynchronously while not adding latency when the user interacts with the UI. Typical problem scenario: user presses alt-tab then a few fast tab tab tab. Here either the CPU will be maxed with the OS calls, and it lags because the CPU is too busy, or the lag is due to draw cycles interacting with the dispatch queues.

Sharing here to document, in case someone wants to dig deeper here.

mfn commented 4 years ago

FTR, from my "user experience" the now-behaviour (using 3.17.1) I consider this problem solved. I.e. form my perspective, this issue can be closed!

Thank you so much 🙏

lwouis commented 4 years ago

@mfn very happy to hear that the performance is great for you. Unfortunately, for users with many windows, there can still be a delay. The more windows open, the longer it takes to build the UI for these users, thus higher latency before we can show them something. We can't really cheat and only load thumbnails for the above the scroll view because with some preferences it's possible to have like 100 windows displayed without having to scroll.

I'm keeping this ticket open because I believe asynchrously loading the thumbnails may a good addition. It could be a preference for users who prefer low-latency over accurate images, and/or it could be some automatic strategy wherein we detect a high number of windows and we switch to that approach, but revert to upfront loading when the user has less than X windows.

Like I said though, the code to do async loading seems complex to me because it's concurrent code, and macOS has no pre-emptive system without using XPC, so you need to use mutexes/semaphores and data races are very easy to do. Also AltTab is already pretty concurrent with OS events happening in the background while the app is open (a window closes, an app quits). My dream would be that someone with strong concurrent programming experience takes my PR and move it forward to something we could add polish to and merge

t-brull commented 4 years ago

Not sure if this was already said above: but maybe one could add an option to the preferences that would turn off the thumbnail computation entirely? I personally don't look at the thumbnails anyway. Also, if you do Command + Tab, it doesn't have any thumbnails (although there it makes more sense, I guess).

lwouis commented 4 years ago

@t-brull this is being discussed in #384

lwouis commented 4 years ago

This is my current plan for this ticket:

nathang21 commented 4 years ago

I really like that idea ^^. As someone with a lot of browser windows open, your explanation captures the typical use cases of which thumbnails are actually important for a given trigger event.

On Mon, Aug 24, 2020 at 9:41 AM lwouis notifications@github.com wrote:

This is my current plan for this ticket:

I would like to avoid having a preference for sync/async load of the thumbnails. I would like to have some kind of heuristic:

  • Always load first N thumbnails sync, so these most-often looked at images are always up-to-date right-away, and exhibit no transformation
  • Depending on the number of pictures, or perhaps previous calibration runs (so we take the specific machine performance into account), we do full sync, or all picture after the Nth picture is async.
  • The async loading should stack if AltTab is triggered multiple times quickly. Previous fetches should be cancelled on UI hide

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/lwouis/alt-tab-macos/issues/171#issuecomment-679239282, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB4CUJSL2KVUNZ3R6GNGS5DSCKJ3HANCNFSM4LFGKZ5A .

lwouis commented 4 years ago

@nathang21 @mfn @mindfulsource Could you guys please try out this local build? I implemented async loading of thumbnails. The first 3 thumbnails are always up-to-date when the UI pops up, but the other thumbnails are later refreshed one by one.

I'm pretty happy with the results. I feel like it's fast enough that it may not need a preference to disable it.

Now, I was testing this in pretty artificial conditions, by plugging my 4K TV and creating lots of windows. I need your help to experience it on your machines, under more realistic conditions. Please try it out and let me know if you think it's an improvement over the current experience 👍

mfn commented 4 years ago

Thanks, running it already since 1h!

I'm not using that many windows I think (18 currently) and not using 4K. My setup is 2 external "FullHD" monitors and MacBook Pro display itself (but I'm using it scaled; "Looks like 1344x840" it says).

At least I can't see any regression and it feels very snappy (but already did before to me; since some improvements you did some many months ago I never had any complaints).

Thanks you so much for you continued dedication! 🙏


For a test I opened ~50-60 Firefox windows (though they're all empty…), it's easy: just "press and hold cmd-n" ;) It took a while for the system to recover from that itself. Anyway, in that case I can feel a bit of latency before seeing something. But since this is a non use-case to me, all is good 😏

lwouis commented 4 years ago

Anyway, in that case I can feel a bit of latency before seeing something.

How does it compare with the public release in that scenario? Better, worse?

I'm actually surprise to hear that because on my laptop if I bring up 200 windows AltTab is still blazing fast to show up. When checking in Instruments, I see around 1-2 frames (16-30ms) of delay to render

nfekete commented 4 years ago

I still feel some kind of lag with this build, but that might be due to system being overloaded with so many open windows anyway and not switching to the AltTab app quick enough. In other cases it feels more snappy than the current stable release. But there is some issue with the display of the window previews. I see that when I do an Alt-Tab and the thumbnails appear, they are more or less correct, then a delayed/deferred update comes where some of the thumbnails gets updated with the wrong thumbnail of another app/window, then another delayed update comes now with the correct thumbnail. Overall there is too much movement in the thumbnail grid and temporarily thumbnails of other windows appear instead of the correct thumbnail for that app. For example, I've temporarily seen one of my open Chrome windows' thumbnail in place of the Slack app's thumbnail.

Update: also, Chrome window thumbnail in place of iTerm2 window thumbnail.

lwouis commented 4 years ago

@nfekete thank you so much for sharing this feedback! You uncovered a logical bug. I think I found the reason why you see the wrong thumbnails in the wrong places. Could you please try this new build? AltTab.app.zip

I see that when I do an Alt-Tab and the thumbnails appear, they are more or less correct, then a delayed/deferred update comes where some of the thumbnails gets updated with the wrong thumbnail of another app/window, then another delayed update comes now with the correct thumbnail. Overall there is too much movement in the thumbnail grid

You say there are 3 "waves" of update? It should be only 1. Could you possible share a video of that in action, using the build I just shared? (Loom is a really fast way to share such video)

ghost commented 4 years ago

Could you please try this new build? AltTab.app.zip

Hah, didn't notice there was a lag until it was pointed out! Wow this test build (quoted one from 30 mins ago) is way snappier. Amazing! A big 'works' from me! I don't notice any lag with any thumbnails. Entire grid of my 28 windows showed immediately.

nfekete commented 4 years ago

You say there are 3 "waves" of update? It should be only 1. Could you possible share a video of that in action, using the build I just shared? (Loom is a really fast way to share such video)

I would say there was the initial display of the thumbnail, then followed by two waves of updates.

I have tried the new build too, and I can confirm the incorrect thumbnail problem that was present in the previous build is now gone and that it's only doing one wave of (visible) update. I put visible there because there might be a second wave as before, but now that the thumbnails are correct it would not be noticeable or visible at all. I tried doing a recording with the previous build but I couldn't reproduce the double update problem again. I'm not sure why.

Most of the time, AltTab appears real quick, most of the time it's perceived as close to instant. Rarely, especially if switching from one complex GUI app to another, then quickly switching back to the previous complex GUI app, there is a slight lag in appearance of the thumbnails, then a delayed update mostly for just the first two thumbnails in the grid (the two thumbnails corresponding to the two complex GUI apps I'm switching back and forth between). This is a huge improvement compared to the current release where - with this amount of open windows - most of the time I had close to one second lag initially, but I could easily trigger 3-4 second lags too, with system under load. The system I am using is a 6 core 2019 MacBook Pro w/ 3k retina + 4k UHD external display, both with fractional scaling - that means most of the time an app window is about 16 million pixels on the external display (fractional scaling @ 2560x1440 is actually 5120x2880 pixels) - I am using full-screen windows most of the time).

lwouis commented 4 years ago

then a delayed update mostly for just the first two thumbnails in the grid

The current code is supposed to work like this:

Could you share a video of the action? I would really like to see it for myself to try to understand what you're witnessing

nfekete commented 4 years ago

Here's a demo video. I recorded the video with KeyCastr running so that you can see when the keys were pressed compared to when AltTab appears on screen and the timing of the updates. Edit: if you take a look at about 30 seconds in the video, after I switch to the SCAD window and do another ⌘⇥, you can see the layout gets updated with the order of the windows changed with the MRU update from the last switch. It takes about 11-12 frames for the AltTab window to appear, and another 15 frames for the first two rows to be updated with the current MRU app order. Don't ask me what is the frame rate of the recording, I wasn't able to figure out. It might be 35 fps or 55 fps, or something else entirely. Edit2: the video is variable frame rate, so I don't know the duration equivalents of those frame counts.

Sometimes I still experience some kind of lag, up to about one second. Many times it's real quick though so I'm not sure where the variation in lag comes from. Note that at this time my system is really heavily overloaded and it might be simply from just MacOS task scheduling, swapping, or some other blocking kernel level task that is preventing AltTab from running.

Side note: I observed that the system in general runs much nicer with application windows minimized. I also set AltTab to only show apps that are not minimized so I can keep the number of non-minimized windows low. This way, usually everything is nice and snappy.

nathang21 commented 4 years ago

@nfekete thank you so much for sharing this feedback! You uncovered a logical bug. I think I found the reason why you see the wrong thumbnails in the wrong places. Could you please try this new build? AltTab.app.zip

This is fantastic, night and day difference for me, much more responsive.

lwouis commented 4 years ago

@nfekete I think at 30s, what we are seeing, is macOS paint cycle being a bit late. It seems to display without the changes for a few frames, then update the view later.

I made a build where I force an update of the view before showing the window. Could you please tell me if the issue still happen? AltTab.app.zip

Regarding the lag, yes it's most likely the computer being slow, not AltTab doing something wrong. AltTab is very dependent on its environment. The thumbnails are coming from the WindowServer. If it's too busy, it will block AltTab while it's getting the info ready.

nfekete commented 4 years ago

I can still see a delayed update that is related to a change in the MRU list in the first few thumbnails. See a recording about it. At about 3 seconds, I switch from the Chrome window to an empty Safari Window, skipping over the iTerm2 window. Then, immediately triggering AltTab again (at 9 seconds), I am presented with a thumbnail order of Chrome, iTerm2, Safari, while in fact, the current app is Safari, the and the MRU apps would be Chrome, iTerm2 in that order. So the displayed thumbnails should be of Safari, Chrome, iTerm2 instead. At 10 seconds, the thumbnails are refreshed, now with the correct order.

Regarding the lag, yes it's most likely the computer being slow, not AltTab doing something wrong. AltTab is very dependent on its environment. The thumbnails are coming from the WindowServer. If it's too busy, it will block AltTab while it's getting the info ready.

True, with this many windows open, WindowServer is using ever more CPU cycles. The more open windows you have, the more CPU it's using, and this happens independent of AltTab, even if I don't use AltTab at all. I found that minimizing windows have a huge impact on this aspect.

Otherwise I have to say I am really satisfied with this performance improvement on AltTab's behalf. I think the WindowServer performance problem can not be avoided with so many open, but not minimized windows, so I'm not sure how much more could be improved on AltTab side. Minimizing them works wonderfully though.

lwouis commented 4 years ago

Could you please try this another build? I tried a more aggressive forcing of the update before the window is displayed AltTab.app.zip

Minimizing them works wonderfully though

Yes, during my tests, I had like 40 Chrome windows open with a big animated gif on each. That way I could see the thumbnails being updated in details as each would update and show a different visual on each alt-tab summon. However, I thought I was going crazy because I was seeing lots of them not updating in AltTab, when I was sure the code was correct.

I think some apps like Chrome notice if their windows are not visible (obstructed by other windows, or minimized), and stop rendering, which reduces the burden on the WindowServer, and the system in general.

nfekete commented 4 years ago

It still happens sometimes, but I would say it's really difficult to trigger it in the sense that I have to really push the system hard to happen. See a short video here.

Analyzing the video, considering what I did, this is what happens here:

  1. I have a Finder Window with Airdrop virtual folder opened as the currently focused application window.
  2. I'm AltTab switching and I select an iTerm2 window, then I release the AltTab modifier key, triggering a focus event for the iTerm2 window. AltTab grid is hidden. Video starts here (I had to crop it here because of some private data was visible in the AltTab grid).
  3. The focus transfer is still in the process (WindowServer busy with so many windows open). First, the Finder window is defocuses (this is already visible in the video).
  4. This is the moment when I trigger AltTab again by pressing the ⌘⇥ shortcut. This is visible in the lower left corner of the video.
  5. The focused iTerm2 window is brought to the front. At this moment in time, AltTab was already triggered in the previous step. Another ⌘⇥ keypress is registered that should move the selection in the AltTab grid from the 2nd to the 3rd position later when the grid appears.
  6. AltTab grid appears with the current app shown as being the Finder/AirDrop window, MRU app being a Chrome window with this page. Another ⌘⇥ keypress is registered that should move the selection in the AltTab grid from the 3rd to the 4th position later when AltTab will process these keypresses.
  7. AltTab grid is refreshed with the correct MRU window list: iTerm2 as the currently focused window, Finder/AirDrop as the last focused window, Chrome with the current page as the previous to last. AltTab grid selection moves to 4th position, catching up with previous keypresses.

Based on the above sequence seems that the behavior of AltTab is correct and the grid refresh is only because of the real underlying sequence of these events.

lwouis commented 4 years ago

Oh I see. Basically AltTab starts rendering, and right after the window focus changes, so AltTab refreshes. This looks normal indeed. In your previous videos, it was different though. You were doing slow actions like slowly pressing alt-tab, then AltTab would update even though nothing changed focus in the background.

Would you say that that second kind of issue is gone with the latest build I shared?

nfekete commented 4 years ago

I am unsure even about the previous behavior, wether we've seen something else or the same thing as this last time. But based on the testing I did last time, this is as much as I could trigger.

Overall it feels really nice and snappy, I am very satisfied with it.

ALB13 commented 4 years ago

Holy COW, this is SOOO much faster! Amazing work, thank-you for taking care of this so fast!

Bummed I missed out on the fun prior to release (it's been one of those weeks), but was pleasantly surprised today when I updated.

jaekyeom commented 4 years ago
  • Potentially, let the user force sync or async. The preference could be: always sync, always async, automatic. I think this is to be avoided though. Ideally the heuristic is good enough that noone wants to change it.

@lwouis Thanks for this amazing work! Are there any plans to add this preference to the app? Thumbnails definitely help in most cases, but sometimes I just want to do a quick alt-tab without even looking at the thumbnails, and I cannot turn on and off "Hide window thumbnails" to make it faster every time ;)

lwouis commented 4 years ago

@jaekyeom in the current release, and for a few releases now, the logic is to drop UI operations such as refreshing thumbnails, when the user releases the shortcut quickly.

If you alt-tab really fast, the app will not refresh thumbnails. The experience should be smooth. Is it not for you?

jaekyeom commented 4 years ago

@lwouis Actually there were some cases that the AltTab window stays open when I alt-tab quickly, but now I get what the "Apparition delay" is for. After adding a small "Apparition delay", it feels very smooth on quick alt-tabs. Thank you!

ADD: I've just noticed that even after increasing the "Apparition delay", the active-app-only switch shortcut always wait for the UI to show up instead of switching to the last window instantly. Is this intentional?

lwouis commented 4 years ago

@jaekyeom yes, AltTab has gotten so fast at this point that on most machines I expect the UI to show within only a few frames (less than 50ms) of you pressing the shortcut. Thus if you release it "fast", you are physically still slower than those 50ms, so the app has no chance to recognize it and cancel showing the UI. This result in a visual flicker of the UI. This is a limitation of the user's finger speed.

The workaround is to allow user to have a window of time, a delay before showing the UI. This is what you have set in the preferences. This way AltTab refrains from showing until that time window is over, then it shows. This lets you release quickly and not see the UI at all

jaekyeom commented 4 years ago

@lwouis Thanks for the answer. To clarify, what I ADDed in my last comment was that the behavior is different for my Shortcut 1 (for "All apps") and Shortcut 2 (for "Active app"). My current setting of the "Apparition delay" is 199ms. If I press Shortcut 1 quickly, then switching happens without the UI showing up. However, when I press Shortcut 2 quickly, windows don't switch instantly and the UI always shows up after the delay.