franciscolourenco / done

A fish-shell package to automatically receive notifications when long processes finish.
MIT License
767 stars 70 forks source link

Done adds delay before command execution on WSL2 #94

Open hajdamak opened 3 years ago

hajdamak commented 3 years ago

As in subject.

franciscolourenco commented 3 years ago

@hajdamak thanks, how much delay are we talking about?

@eugene-babichenko @meatcar Any idea about this? Can you reproduce?

hajdamak commented 3 years ago

@franciscolourenco About half a second I guess, enough to be annoying. This happens regardless if I have BurtToast installed or not. Disabling Done makes it instant.

meatcar commented 3 years ago

I can confirm that this is an issue. This is due to powershell invocations being slow under WSL2, and Done runs powershell to fetch the current focused window twice per command invocation, plus once more for the notification on mismatch.

A theoretically possible workaround would be to spin up a long-living powershell process, and communicate with it through unix sockets, but that's pretty involved.

Currently I minimize latency by configuring WSL to not include Windows' PATH, then proxy a powershell command. It doesn't fix the latency involved around invoking powershell, but it's good enough for me.

/etc/wsl.conf:

[interop]
appendWindowsPath = false

A file called powershell.exe in my $PATH:

#!/bin/sh
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -NonInteractive –ExecutionPolicy Bypass "$@"
eugene-babichenko commented 3 years ago

Confirming this issue, happens for me too. Will take my time to investigate.

It might be due to some broken update. The old ngen update trick partially did it for me (time __done_get_focused_window_id is 480 ms which is still a lot, but less than 1.5 s).

I will look into ways to reduce the overall PowerShell overhead. What is bugging me the most right now is that it is not looking like the overhead of WSL/Windows boundary, but like Powershell is being very slow to start itself.

eugene-babichenko commented 3 years ago

I've laid the foundation for using the background PowerShell process (link to the script provided). This is using pipes for the IPC instead of domain sockets. The end result should be a single PowerShell instance for all shells using an exclusive flock to synchronize accesses between multiple fish instances.

https://github.com/eugene-babichenko/done/blob/faster-powershell/conf.d/powershell-support-proc.ps1

franciscolourenco commented 3 years ago

I don't use Windows so have to stay out of this @eugene-babichenko, but PRs are still welcome 👍

eugene-babichenko commented 3 years ago

I am going to work under Linux for some time, and I will not be working on this issue during that time. If anybody wants to pick up my work, feel free to do so.

acomagu commented 1 year ago

How about including Windows binary to the plugin?

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    static void Main()
    {
        Console.WriteLine(GetForegroundWindow());
    }
}

Compile this(instant way is C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe program.cs) and put the executable in ~/.config/fish/conf.d and finally call it from done.fish.

diff --git a/conf.d/done.fish b/conf.d/done.fish
index b1a989b..1fc2f96 100644
--- a/conf.d/done.fish
+++ b/conf.d/done.fish
@@ -92,17 +92,7 @@ function __done_get_focused_window_id
         and xprop -grammar >/dev/null 2>&1
         xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2
     else if uname -a | string match --quiet --ignore-case --regex microsoft
-        __done_run_powershell_script '
-Add-Type @"
-    using System;
-    using System.Runtime.InteropServices;
-    public class WindowsCompat {
-        [DllImport("user32.dll")]
-        public static extern IntPtr GetForegroundWindow();
-    }
-"@
-[WindowsCompat]::GetForegroundWindow()
-'
+        env (dirname (status --current-filename))/program.exe
     else if set -q __done_allow_nongraphical
         echo 12345 # dummy value
     end