none
关于操作系统长时间运行后调用Process.GetProcesses()的效率问题

    问题

  • 我现在开发的一个功能需要定时扫描正在运行的进程列表,以便于及时把意外退出的程序重新启动。

    我使用Process.GetProcesses()获取操作系统当前运行的进程列表,在大多数的电脑上这并没有产生性能问题。

    但是当我部署到一台长时间运行的服务器上时(已经连续运行147天,新开的PID已排到近百万),调用Process.GetProcesses()的处理时间竟然高达100毫秒,而一般情况下调用Process.GetProcesses()的时间消耗大概是几毫秒以内,这对我正在使用的系统性能造成了一定的影响。

    不知道是否有谁可以告诉我该如何解决这样的一个问题?

    谢谢!


    • 已编辑 TimzChen 2017年2月25日 8:24
    2017年2月25日 6:31

答案

  • Hi,

    >>" 无论我是调用Process.GetProcesses(),或是调用Process.GetProcessesByName,还是调用 "

    从这个reply建议使用C++代码来节省资源,因为C#始终都是需要转成中间语言,然后在转成汇编语言,这就会导致开启的时间可能会变长。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Hi Hart,

    据我所了解,C#是一门即时编译(JIT)语言,一个方法只在首次调用时才会编译(在运行时也可以明显察觉到方法在首次执行时耗时较久),以后对该方法的所有调用都以本地代码的形式全速执行,无需重新编译成本地代码。这可以在《CLR VIA C#》的第1章第4节中找到对应的参考信息。

    我觉得调用Process.GetProcesses...的性能问题极有可能是由于操作系统没有及时释放过时的进程资源,导致操作系统长时间运行后残留的进程信息过多,造成调用Process.GetProcesses...的缓慢。因为我发现重启电脑之后,这个方法的调用速度就已经变为正常,但是我依然可以预见这个问题在将来还会发生。

    虽然提高Process.GetProcesses...的性能从C#开发的角度来说有点无望,但是我在另一个提问中找到了另一种思路。(抱歉回复不能包含链接)

    Maybe obtain the Process object, then use WaitForExit. Or set the EnableRaisingEvents to true and handle the Exited event. Then you do not need the periodic loops.

    感谢您的回复!





    2017年2月28日 13:15

全部回复

  • Hi TimzChen,

    感谢你在MSDN论坛发帖。

    >>" 但是当我部署到一台长时间运行的服务器上时(已经连续运行147天,新开的PID已排到近百万),调用Process.GetProcesses()的处理时间竟然高达100毫秒,而一般情况下调用Process.GetProcesses()的时间消耗大概是几毫秒以内 "

    如果一台电脑运行就几个小时,但是新开的PID已经排到近百万,调用GetProcesses,也会耗时100毫秒吗?

    我在想是不是之前运行的程序导致内存垃圾太多,CLR还没有来的及释放这些垃圾,导致好使比较多。

    你是如何调用GetProcesses函数的?

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年2月27日 6:38
    版主
  • Hi TimzChen,

    感谢你在MSDN论坛发帖。

    >>" 但是当我部署到一台长时间运行的服务器上时(已经连续运行147天,新开的PID已排到近百万),调用Process.GetProcesses()的处理时间竟然高达100毫秒,而一般情况下调用Process.GetProcesses()的时间消耗大概是几毫秒以内 "

    如果一台电脑运行就几个小时,但是新开的PID已经排到近百万,调用GetProcesses,也会耗时100毫秒吗?

    我在想是不是之前运行的程序导致内存垃圾太多,CLR还没有来的及释放这些垃圾,导致好使比较多。

    你是如何调用GetProcesses函数的?

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Hi Hart, 感谢您的回答!

    我还没有测试过一台电脑运行几个小时就可以把PID排到近百万,如果有需要,我迟些会测试。

    我在论坛上看到有人曾经问过和我现在提问相似的问题,但是并没有找到对应的解决方案。

    无论我是调用Process.GetProcesses(),或是调用Process.GetProcessesByName,还是调用Process.GetProcessById,这些调用需要的处理时间几乎是一样长的。若调用WMI的话,时间还将更长。

    我的调用代码是下面这样的,这一行代码处理的时间,几乎占据了我一次处理的所有时间:

    var currentProcesses = Process.GetProcesses();


    • 已编辑 TimzChen 2017年2月27日 9:15
    2017年2月27日 9:13
  • Hi,

    >>" 无论我是调用Process.GetProcesses(),或是调用Process.GetProcessesByName,还是调用 "

    https://social.msdn.microsoft.com/Forums/zh-CN/b30f4140-8d1c-4cd1-bc14-90caf804e8b9/processgetprocessescpu?forum=visualcshartzhchs

    从这个reply建议使用C++代码来节省资源,因为C#始终都是需要转成中间语言,然后在转成汇编语言,这就会导致开启的时间可能会变长。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年2月28日 5:44
    版主
  • Hi,

    >>" 无论我是调用Process.GetProcesses(),或是调用Process.GetProcessesByName,还是调用 "

    从这个reply建议使用C++代码来节省资源,因为C#始终都是需要转成中间语言,然后在转成汇编语言,这就会导致开启的时间可能会变长。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Hi Hart,

    据我所了解,C#是一门即时编译(JIT)语言,一个方法只在首次调用时才会编译(在运行时也可以明显察觉到方法在首次执行时耗时较久),以后对该方法的所有调用都以本地代码的形式全速执行,无需重新编译成本地代码。这可以在《CLR VIA C#》的第1章第4节中找到对应的参考信息。

    我觉得调用Process.GetProcesses...的性能问题极有可能是由于操作系统没有及时释放过时的进程资源,导致操作系统长时间运行后残留的进程信息过多,造成调用Process.GetProcesses...的缓慢。因为我发现重启电脑之后,这个方法的调用速度就已经变为正常,但是我依然可以预见这个问题在将来还会发生。

    虽然提高Process.GetProcesses...的性能从C#开发的角度来说有点无望,但是我在另一个提问中找到了另一种思路。(抱歉回复不能包含链接)

    Maybe obtain the Process object, then use WaitForExit. Or set the EnableRaisingEvents to true and handle the Exited event. Then you do not need the periodic loops.

    感谢您的回复!





    2017年2月28日 13:15
  • Hi,

    很高兴听到,你找到另外一种解决方案。

    对于这个问题应该是一个很常见的问题,我希望你能记有用的回复作为答案,这样会帮助遇到相同问题的人。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月1日 1:38
    版主