Windows XP上的Git sh.exe进程分叉问题,慢吗?
Posted
技术标签:
【中文标题】Windows XP上的Git sh.exe进程分叉问题,慢吗?【英文标题】:Git sh.exe process forking issue on windows XP, slow? 【发布时间】:2011-08-16 15:13:44 【问题描述】:Git 对我的工作流程至关重要。我在具有 3GB RAM 的四核机器上在 Windows XP 上运行 MSYS Git,通常它反应灵敏且速度快。
突然出现了一个问题,即从 Git Bash 命令提示符运行任何命令需要超过 30 秒,包括 ls
或 cd
。有趣的是,从 bash 提示符看来 ls
运行得相当快,然后我可以看到来自 ls
的输出,但是提示符需要大约 30 秒才能返回。如果我切换到 Windows 命令提示符(通过从开始菜单运行 cmd
)git 相关命令也需要永远,即使只是运行。例如git status
可能需要将近一分钟才能发生任何事情。有时这些过程根本没有完成。
请注意,我安装了“MSYS Git”以及用于MinGW
和make
之类的常规“MSYS”。
我认为问题与位于C:\Program Files\Git\bin
的sh.exe
有关。当我从 bash 提示符运行 ls
时,或者当我从 Windows 提示符调用 git
时,任务管理器最多显示四个来来去去的 sh.exe
进程实例。
这里我在等待ls
返回,你可以看到任务管理器有git.exe
在运行和sh.exe
的四个实例:
如果我 ctrl-c
位于 ls
的中间,我有时会收到以下错误:
sh.exe": fork: Resource temporarily unavailable
0 [main] sh.exe" 1624 proc_subproc: Couldn't duplicate my handle<0x6FC> fo
r pid 6052, Win32 error 5
sh.exe": fork: Resource temporarily unavailable
或者对于git status
:
$ git状态
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
我能否解决这个问题,让 git 再次快速运行,如果可以,如何解决?
我尝试过的事情:
重启 将 MSYS Git 升级到最新版本并重新启动 将 MSYS 升级到最新版本并重启 卸载 MSYS 并单独卸载并重新安装 MSYS Git 并重新启动我非常希望不要擦拭我的盒子并重新安装 Windows,但如果我无法解决这个问题,我会这样做。如果运行 git status
或 cd.
需要超过 30 秒,我将无法再编写代码
【问题讨论】:
您是否尝试过这些非常相似的问题的答案? Git/Bash is extremely slow in Windows 7 x64, Msysgit bash is horrendously slow in Windows 7. @Greg:我看到了这些问题,但解决方案是特定于 Windows 7 的,所以我无法像在 Windows XP 上那样真正尝试它们。 如果您看到这些问题,您会看到$PS1='$ '
选项,这是答案之一。
啊,是的。我现在看到了。好吧,我想我只是仔细检查了标记为正确的答案和其他获得投票的答案。所有这些确实是 Windows 7 特定的解决方案。
这些答案似乎都没有明确提到分叉错误。我也看到了这些(是的,Git 在这台工作 PC 上非常慢)。
【参考方案1】:
通常,当程序需要 30 秒来完成本应是瞬时的事情时,更可能是 I/O 超时问题,通常是网络问题,而不是 CPU 的速度或您拥有的 RAM 量。您可能想知道网络是如何参与其中的,但这是一个合理的问题(我也不知道您的系统)。
Msysgit 安装一个特殊提示符,该提示符运行一个特殊函数__git_ps1
,它在提示符中显示一些有用的信息。您可以使用echo $PS1
看到这一点,对于我的系统显示:
$ echo $PS1
\[\033]0;$MSYSTEM:\w\007 \033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\] $
此额外信息完全是可选的,您可以将其关闭。因此,请在 Msysgit 窗口中尝试以下操作:
$ PS1='$ '
$
这会将提示重置为默认的$
,并且不会尝试在提示中运行和命令。如果这解决了您的延迟问题,那么很可能是 __git_ps1
函数。尝试手动运行它:
$ __git_ps1
(master)
看看返回需要多长时间。
您可以通过从C:\Program Files\Git\etc\profile
中删除调用__git_ps1
的行来解决此问题:
#Comment the lines below
#PS1='\[\033]0;$MSYSTEM:\w\007
#\033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\]
#$ '
【讨论】:
@manojids:进一步检查,从 Windows 命令提示符运行git
最初很快。它从缓慢的提示运行git status
或git anything
。在我运行之后,即使单独运行git
也很慢。我现在正在检查 Greg 的答案。
无论如何,修复将无济于事,因为它与 cmd 完全无关。
太棒了!如果我运行$ PS1='$ '
,一切都会恢复到正常的活泼自我。如果我运行__git_ps1
,一切都会停止,大约一分钟后,我ctrl-c
就会退出。所以现在的问题是,如何在每个新的 Git bash 窗口中自动获取PS1='$ '
?仅仅打开一个新的 Git bash 窗口就需要 30 秒。
@manojlds:我同意这很奇怪。从cmd
运行git status
仍然很慢。也许git
可以调用在sh.exe
中运行的其他进程,即使它们只是从cmd
调用的?
好的!我对您的回答进行了编辑,说您可以通过注释掉C:\Program Files\Git\etc\profile
中的相应行来解决问题。非常感谢。巨大的帮助。【参考方案2】:
虽然 Greg 的回答解决了直接的速度问题,但我觉得它只是掩盖了问题,并没有解决它。
我开始让 git bash 运行缓慢,并按照 Greg 描述的步骤确定 __git_ps1
是罪魁祸首。
我没有修改命令提示信息(我发现它显示的信息很有用),我找到了一个对我有用的解决方案,在一篇博文中进行了描述:
Solution to slow Git bash when logged in as a domain user
在网上搜索了一下,我发现 git 使用默认主页, 我的帐户设置为网络帐户。这说明 git 会 一直在看这个目录,导致延迟。
为了解决这个问题,我创建了一个本地用户环境变量,覆盖 默认值,并将其设置为 %USERPROFILE% 指向 c:\users[用户名]。
同样的解决方案也发布在 SO answering a similar question。
添加环境变量使 git 恢复到全速,我仍然得到命令行信息。
【讨论】:
【参考方案3】:如果在同时运行多个 Git 命令时看到速度变慢,可能是由于 msysgit 中的内核锁定问题
我们看到在某些情况下,多个 git.exe 实例都会等待同一个内核对象(在 WaitForSingleObject()
内),这实际上意味着一次只能在系统上运行一个 git 命令。
请看这里:
使用 ProcessExplorer,我们可以看到所有 git.exe 进程都卡在这里:
ntoskrnl.exe!KeWaitForMultipleObjects+0xc0a
ntoskrnl.exe!KeAcquireSpinLockAtDpcLevel+0x732
ntoskrnl.exe!KeWaitForMutexObject+0x19f
ntoskrnl.exe!FsRtlCancellableWaitForMultipleObjects+0x5e
ntoskrnl.exe!FsRtlCancellableWaitForSingleObject+0x27
这似乎与这个问题有关:http://code.google.com/p/msysgit/issues/detail?id=320 不是 Git,而是伪 Linux 运行时 (mingw) 似乎包含问题。
我们将用于运行应用程序的用户帐户从 SYSTEM 更改为交互式用户帐户,内核对象等待消失了:
健康的 git.exe 进程
因此,您看到的减速可能与某种内核对象争用有关 - 只有当前一个 git 命令释放内核锁时,其他命令才能运行。
尝试更改您运行 git 命令的用户帐户,看看这是否解决了问题 - 它对我们有用。
【讨论】:
【参考方案4】:我在 Windows XP 机器上遇到了缓慢的进程分叉问题。有时,进程分叉需要几分钟。
对我来说,解决方法是清空计算机的 TEMP 文件夹。计算机是共享资源,多年来一直在其中积累文件。
【讨论】:
【参考方案5】:所以我们也遇到了这个问题,我想我们最终将其追溯到 msys 对 Windows 安全模型的实现。我将尝试发布该问题的简短摘要:
截图: 卡住的 sh.exe 的堆栈跟踪。注意 msys-1.0.dll 何时调用 NetServerEnum()
这就是 sh.exe 被阻止 30 秒时发生的情况。所以NetServerEnum()
只在msys
中调用了一处,security.cc:228在get_lsa_srv_inf()
中调用,由get_logon_server()
调用,get_logon_server_and_user_domain()
在create_token()
中调用,由seteuid()
调用在setuid()
调用的syscalls.cc中。
所以本质上发生的事情是,当初始化 msys DLL 并且 sh.exe 尝试调用 setuid()
时,msys 尝试忠实地遵守 Windows 安全模型并尝试从您的域中查找域服务器列表/工作组。不幸的是,与 linux 不同的是,对于 Windows,这是一个阻塞调用,需要 5-30 秒才能完成/超时,实际上对于 git 来说是不必要的。
我们的解决方案是通过在 winsup.cc 中将 has_security 设置为 false 来创建禁用安全“功能”的新 msys.dll。 msysgit 自带的 bash/sh.exe 和我们新版本的 msys.dll 不兼容,所以我们也不得不从头编译一个新的 bash.exe,不知道为什么。最终结果是 sh.exe 不再尝试进行这些 NetServerEnum 调用并运行 lickity split。
【讨论】:
【参考方案6】:如果 sh 在 NetServerEnum 中挂起枚举登录服务器,请尝试将 LOGONSERVER 环境变量设置为实际的登录服务器。
【讨论】:
以上是关于Windows XP上的Git sh.exe进程分叉问题,慢吗?的主要内容,如果未能解决你的问题,请参考以下文章