lf icon indicating copy to clipboard operation
lf copied to clipboard

Slow startup on Windows

Open kitsugo opened this issue 2 years ago • 4 comments

I'm experiencing a very slow startup when using LF on Windows. No matter whether I open it in PowerShell or Cmd, it takes roughly 7-10 seconds until it's shown after entering the command. It also makes no difference whether I use a dedicated terminal like Windows Terminal or the built-in PS1/Cmd prompt.

After LF has started for the first time, quitting and starting it again is as fast as expected. However, after some time, it seems like it somehow is "unloaded" and then the startup will take a long time again. I do not have this issue on Linux. LF always starts immediately there. I've the latest amd64 version of LF for Windows installed and put the executable in my PATH.

Any advice on how to debug this startup issue would be greatly appreciated.

kitsugo avatar Jan 30 '23 14:01 kitsugo

I also have slow startup (~5 sec). Found that my issue is related to my configuration: I am creating some dynamic mappings during start. And apparently each lf -remote call takes ~1.5 sec. So doing 3 mappings and I got such delay.

Here is my init, part of my config (powershell)

%{{
	# Adding shortcut for each drive
	foreach($drive in (Get-PSDrive -PSProvider FileSystem))
	{
		lf -remote "send $env:id map g$($drive.Name.ToLower()) cd '$($drive.Root)'"
	}
}}

Is there any other way to have such custom mappings?

jdfa avatar Feb 07 '23 22:02 jdfa

it is slow because of os/user package's GetCurrent() function, maybe is go's bug , i dont know, problem is in file os_windows.go(59)

you can do like this, print your user info to screen ,and manual setup your user struct like below code.

	u := &user.User{
		Uid:      "xxx",
		Gid:      "xxx",
		Username: "xxx",
		Name:     "xxx",
		HomeDir:  "xxx",
	}
	// u, err := user.Current()
	// if err != nil {
	// 	log.Printf("user: %s", err)
	// }
	fmt.Println(u.Uid, u.Gid, u.Username, u.Name, u.HomeDir)
	// panic("ok")

this can only work for current user, if you change computer or user ,you need do it again.

soluty avatar Jun 28 '23 04:06 soluty

On my private machine it turns on in an instant while on my work machine it takes a couple of seconds. Any idea where should I look for a possible cause?

Relative to jdfa's answer I don't do anything complicated (I think) in my powershell profile.

I don't know any Go so I don't understand soluty's reply and whether it can help or not.

Hollow-Glitch avatar Oct 21 '23 09:10 Hollow-Glitch

My first uneducated guess: some sort of security scanner, antivirus, or similar takes a long time to decide whether lf is OK to run. This problem would get compounded if lf calls itself with lf --remote enough times during initialization.

If this is the problem, you could try whitelisting lf in all these scanners. If that's not possible, I'm not sure what could be done about it.

ilyagr avatar Oct 21 '23 20:10 ilyagr

Adding the lf.exe directory to the exclusions list on windows defender sped subsequent start up times to near instant. Even when I start a new terminal session it now boots instantly. However, the very first time I call lf (after a windows reboot) it is still slow to start.

Laurence-NZ avatar Feb 24 '24 23:02 Laurence-NZ

I think this problem occurs when the machine is joined in the Active Directory. It seems that user.Current() makes a request get the user info from the active directory which will time out, and then it will fallback on the local info. If you stop the network on your machine you'll probably see that the delay will disappear because the request will fail right away.

This article shows the same problem with the docker commands. https://www.fearofoblivion.com/slow-docker-commands-on-domain-joined-pc

The workaround proposed by @soluty seems to solve the issue, if you hardcode your user info on all places where user.Current() is called, the delay disappears.

The reason why the first calls is very slow, then become faster is probably because the user.Current() function caches the result as it says here. After some time the cache will probably be invalidated and the delay will reappear. https://pkg.go.dev/os/user#Current

Since only HomeDir and Username are used from the user info, a more permanent solution could be the possibility to set the homeDir and Username directly from the lfrc and not making the call to user.Current() in that case.

Catalyn45 avatar Feb 25 '24 16:02 Catalyn45

I could try to implement this fix myself if @gokcehan thinks this is good way to solve this.

I think this problem occurs when the machine is joined in the Active Directory. It seems that user.Current() makes a request get the user info from the active directory which will time out, and then it will fallback on the local info. If you stop the network on your machine you'll probably see that the delay will disappear because the request will fail right away.

This article shows the same problem with the docker commands. https://www.fearofoblivion.com/slow-docker-commands-on-domain-joined-pc

The workaround proposed by @soluty seems to solve the issue, if you hardcode your user info on all places where user.Current() is called, the delay disappears.

The reason why the first calls is very slow, then become faster is probably because the user.Current() function caches the result as it says here. After some time the cache will probably be invalidated and the delay will reappear. https://pkg.go.dev/os/user#Current

Since only HomeDir and Username are used from the user info, a more permanent solution could be the possibility to set the homeDir and Username directly from the lfrc and not making the call to user.Current() in that case.

Catalyn45 avatar Feb 25 '24 16:02 Catalyn45