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 秒,包括 lscd。有趣的是,从 bash 提示符看来 ls 运行得相当快,然后我可以看到来自 ls 的输出,但是提示符需要大约 30 秒才能返回。如果我切换到 Windows 命令提示符(通过从开始菜单运行 cmd)git 相关命令也需要永远,即使只是运行。例如git status 可能需要将近一分钟才能发生任何事情。有时这些过程根本没有完成。

请注意,我安装了“MSYS Git”以及用于MinGWmake 之类的常规“MSYS”。

我认为问题与位于C:\Program Files\Git\binsh.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 statuscd. 需要超过 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 statusgit 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进程分叉问题,慢吗?的主要内容,如果未能解决你的问题,请参考以下文章

windows下git中sh.exe中文显示乱码问题解决

windows下git中sh.exe中文显示乱码问题解决

设置 git bash 以使用 Windows 上的选项卡

MS-Windows中的Git命令行

如何让 Git 推/拉通过 Windows 7 防火墙?

ide phpStorm使用git的命令行工具