{"id":1723,"date":"2023-04-22T16:12:05","date_gmt":"2023-04-22T08:12:05","guid":{"rendered":"https:\/\/blog.dynox.cn\/?p=1723"},"modified":"2023-08-10T16:33:26","modified_gmt":"2023-08-10T08:33:26","slug":"windows%e8%bf%9b%e7%a8%8bcpu%e3%80%81%e5%86%85%e5%ad%98%e7%ad%89%e8%b5%84%e6%ba%90%e9%99%90%e5%88%b6","status":"publish","type":"post","link":"https:\/\/blog.dynox.cn\/?p=1723","title":{"rendered":"Windows\u8fdb\u7a0bCPU\u3001\u5185\u5b58\u7b49\u8d44\u6e90\u9650\u5236"},"content":{"rendered":"<div class=\"gruber-markdown\"><p>Windows\u81ea\u8eab\u6ca1\u6709\u63d0\u4f9b\u7c7b\u4f3cLinux cgroup\u7684\u80fd\u529b\u6765\u9650\u5236\u8fdb\u7a0b\u6216\u8fdb\u7a0b\u7ec4\u7684\u8d44\u6e90\u5360\u7528\uff0c\u8fdb\u7a0bCPU\/IO\/\u5185\u5b58\/\u7f51\u7edc\u7b49\u8d44\u6e90\u7684\u63a7\u5236\u53ea\u80fd\u7531\u81ea\u5df1\u5b9e\u73b0\u3002\u76ee\u524d\u5df2\u6709\u7b2c\u4e09\u65b9\u7684\u5b9e\u73b0\uff0c\u4e3b\u8981\u662f\u9650\u5236\u8fdb\u7a0bCPU\u7684\u5360\u7528\uff0c\u5982\u6587\u6863 &lt; 21 Best Ways to Limit the CPU Usage of a Process &gt; \u6240\u63cf\u8ff0\u7684BES\uff0cProcess Tamer\u7b49\u8f6f\u4ef6\u3002\u81eaWindows 8\u53caServer 2012\u5f00\u59cbWindows\u7cfb\u7edf\u6709\u63d0\u4f9b\u4ee5job\u4e3a\u5355\u4f4d\u7684CPU\u5360\u7528\u53ca\u5185\u5b58\u4e0a\u9650\u8bbe\u7f6e\uff0c\u4e4b\u524d\u7684\u7248\u672c\u5219\u53ea\u80fd\u4ee5\u8fdb\u7a0b\u6216\u7ebf\u7a0b\u4e3a\u5355\u4f4d\u8fdb\u884c\u9650\u5236\u3002<\/p>\n<h2>\u8fdb\u7a0bCPU\u5360\u7528\u9650\u5236\u65b9\u6848<\/h2>\n<p>\u5373\u65f6\u8f6e\u8be2\u7cfb\u7edf\u6240\u6709\u8fdb\u7a0b(\u7ebf\u7a0b)\u7684CPU\u5360\u7528\uff0c\u5f53\u53d1\u73b0\u6240\u8bbe\u5b9a\u8fdb\u7a0b\u6709\u8d85\u6807\u65f6\u5f3a\u5236\u6682\u505c\u8fdb\u7a0b\u6240\u6709\u7ebf\u7a0b\u7684\u6267\u884c\uff0c\u7136\u540e\u5728\u9002\u5f53\u7684\u65f6\u673a\u518d\u6062\u590d\u6267\u884c\u3002\u5176\u4e2d\u6240\u6d89\u53ca\u6280\u672f\u70b9\uff1a<\/p>\n<h3>\u8fdb\u7a0bCPU\u5360\u7528\u67e5\u8be2 GetProcessTimes<\/h3>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL GetProcessTimes(\n  [in]  HANDLE     hProcess,\n  [out] LPFILETIME lpCreationTime,\n  [out] LPFILETIME lpExitTime,\n  [out] LPFILETIME lpKernelTime,\n  [out] LPFILETIME lpUserTime\n);<\/code><\/pre>\n<p>\u6b64\u51fd\u6570\u53ef\u4ee5\u83b7\u53d6\u8fdb\u7a0b\u4ece\u521b\u5efa\u81f3\u5f53\u524d\u7684\u603b\u8fd0\u884c\u65f6\u95f4\u53ca\u603b\u7684CPU\u65f6\u95f4\uff0c(KernelTime + UserTime) &lt; \u7cfb\u7edfCPU\u6570 * (\u5f53\u524d\u65f6\u95f4 - CreationTime)<\/p>\n<h3>\u7ebf\u7a0bCPU\u5360\u7528\u67e5\u8be2 GetThreadTimes<\/h3>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL GetThreadTimes(\n  [in]  HANDLE     hThread,\n  [out] LPFILETIME lpCreationTime,\n  [out] LPFILETIME lpExitTime,\n  [out] LPFILETIME lpKernelTime,\n  [out] LPFILETIME lpUserTime\n);<\/code><\/pre>\n<p>QueryThreadCycleTime\u53ef\u4ee5\u63d0\u4f9b\u66f4\u7cbe\u51c6\u7684CPU\u65f6\u95f4\u6570\u636e\uff0c\u5355\u4f4d\u4e3aCPU\u65f6\u949f\u5468\u671f<\/p>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL QueryThreadCycleTime(\n  [in]  HANDLE   ThreadHandle,\n  [out] PULONG64 CycleTime\n);<\/code><\/pre>\n<h3>\u7ebf\u7a0b\u6682\u505c\u53ca\u6062\u590d<\/h3>\n<p>Windows\u5e73\u53f0\u6ca1\u6709\u63d0\u4f9b\u6682\u505c\u6574\u4e2a\u8fdb\u7a0b\u7684\u652f\u6301\u51fd\u6570\uff0c\u53ea\u80fd\u4ee5\u7ebf\u7a0b\u4e3a\u5355\u4f4d\u6765\u64cd\u4f5c\uff0c\u5373SuspendThread\u53caResumeThread:<\/p>\n<pre><code class=\"prettyprint\" class=\"language-c\">DWORD SuspendThread(\n  [in] HANDLE hThread\n);\nDWORD ResumeThread(\n  [in] HANDLE hThread\n);<\/code><\/pre>\n<h3>CPU\u4eb2\u548c\u6027\u8bbe\u7f6e: SetProcessAffinityMask<\/h3>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL SetProcessAffinityMask(\n  [in] HANDLE    hProcess,\n  [in] DWORD_PTR dwProcessAffinityMask\n);<\/code><\/pre>\n<p>\u6b64\u51fd\u6570\u53ef\u4ee5\u9650\u5b9a\u8fdb\u7a0b\u53ca\u5176\u6240\u6709\u7ebf\u7a0b\u6240\u80fd\u4f7f\u7528\u7684CPU\uff0c\u6545\u4e00\u5b9a\u7a0b\u5e8f\u4e0a\u4ea6\u9650\u5b9a\u4e86\u8fdb\u7a0b\u6700\u5927\u7684\u7cfb\u7edfCPU\u5360\u7528\u7387\u3002<\/p>\n<pre><code class=\"prettyprint\" class=\"language-c\">DWORD_PTR SetThreadAffinityMask(\n  [in] HANDLE    hThread,\n  [in] DWORD_PTR dwThreadAffinityMask\n);<\/code><\/pre>\n<p>\u6b64\u51fd\u6570\u53ef\u5355\u72ec\u9650\u5236\u7279\u5b9a\u7ebf\u7a0b\u7684CPU\u4eb2\u548c\u6027\u3002<\/p>\n<h3>\u8fdb\u7a0b\u4f18\u5148\u7ea7\u8bbe\u7f6e: SetPriorityClass<\/h3>\n<p>\u4f18\u5148\u7ea7\u89e3\u51b3\u7684\u662f\u4f18\u5148\u8fd0\u884c\u53ca\u9000\u8ba9CPU\u7684\u95ee\u9898\uff0c\u672c\u8d28\u4e0a\u5e76\u4e0d\u80fd\u9650\u5b9aCPU\u5360\u7528\uff0c\u53ea\u662f\u4f18\u5148\u7ea7\u9ad8\u4e8e\u5f53\u524d\u4efb\u52a1\u7684\u5fd9\u788c\u7684\u65f6\u5019\uff0c\u5f53\u524d\u8fdb\u7a0b\u4f1a\u4e3b\u52a8\u9000\u8ba9CPU\n\u7ebf\u7a0b\u4f18\u5148\u7ea7\u8bbe\u7f6e\uff1aSetThreadPriority<\/p>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL SetThreadPriority(\n  [in] HANDLE hThread,\n  [in] int    nPriority\n);<\/code><\/pre>\n<h3>Job Objects<\/h3>\n<p>Windows\u7cfb\u7edf\u63d0\u4f9b\u4e86Job\u7684\u6982\u5ff5\u7528\u4ee5\u7ba1\u7406\u591a\u4e2a\u8fdb\u7a0b\uff0c\u53ef\u4ee5\u9650\u5236Job\u5bf9\u8c61\u5185\u6240\u6709\u8fdb\u7a0b\u53ca\u671f\u7ebf\u7a0b\u7684CPU\u6838\u5fc3\u5360\u7528\u3001CPU\u5360\u7528\u53ca\u5185\u5b58\u5206\u914d\u4e0a\u9650\u7b49\uff0c\u5747\u901a\u8fc7SetInformationJobObject\u6765\u5b9e\u73b0\uff0c\u5177\u4f53\u7684CPU\u9650\u5236\u7531JOBOBJECT_CPU_RATE_CONTROL_INFORMATION\u7ba1\u7406\uff0c\u5185\u5b58\u9650\u5236\u5219\u7531JOBOBJECT_EXTENDED_LIMIT_INFORMATION\u6765\u7ba1\u7406\u3002<\/p>\n<pre><code class=\"prettyprint\" class=\"language-c\">BOOL SetInformationJobObject(\n  [in] HANDLE             hJob,\n  [in] JOBOBJECTINFOCLASS JobObjectInformationClass,\n  [in] LPVOID             lpJobObjectInformation,\n  [in] DWORD              cbJobObjectInformationLength\n);<\/code><\/pre>\n<p>\u9700\u8981\u6ce8\u610f\u7684\u662fCPU\u5360\u7528\u8bbe\u7f6e\u53ea\u6709<strong>Windows 8\u53caServer 2012\u4e4b\u540e<\/strong>\u7684\u7248\u672c\u6709\u6548\u3002<\/p>\n<h3>CPU Sets<\/h3>\n<p>\u6b64\u90e8\u5206\u53ea\u9650\u5b9a\u4e86CPU Affinity\u5c5e\u6027<\/p>\n<h2>\u5b9e\u9a8c\u9a8c\u8bc1<\/h2>\n<p>\u53ef\u4ee5\u76f4\u63a5\u5229\u7528\u5f00\u6e90\u9879\u76eego-winjob\u9a8c\u8bc1\uff0c\u9a8c\u8bc1\u7cfb\u7edfWindows 8 x64\uff0cgo-winjob git repo:\n<a href=\"https:\/\/github.com\/kolesnikovae\/go-winjob\">https:\/\/github.com\/kolesnikovae\/go-winjob<\/a><\/p>\n<h3>\u9a8c\u8bc1\u7a0b\u5e8f<\/h3>\n<pre><code class=\"prettyprint\" class=\"language-c\">#include &amp;lt;stdio.h&amp;gt;\n#include &amp;lt;stdlib.h&amp;gt;\n\nvoid main(int argc, char *argv[])\n{\n        unsigned long total = 0, count = 0, i = 0;\n\n        while (1) {\n                if (malloc(1024)) {\n                        total += 1024;\n                        count++;\n                }\n                if (!(++i &amp;amp; 4095))\n                        printf(&amp;quot;alloc: %u size: %u bytes\\n&amp;quot;, count, total);\n    }\n}<\/code><\/pre>\n<h3>\u65e0\u9650\u5236<\/h3>\n<p>\u5728\u65e0\u9650\u5236\u7684\u60c5\u51b5\u4e0b\uff0c\u6b64\u8fdb\u7a0b\u4f1a\u5360\u6ee1\u4e00\u4e2aCPU\u6838\u5fc3\uff0ccommit\u5185\u5b58\u603b\u5360\u7528\u8fbe2G\n<img decoding=\"async\" src=\"https:\/\/blog.dynox.cn\/wp-content\/uploads\/2023\/04\/winjob-cpu-unlimit.png\" alt=\"CPUStress unlimited\" \/><\/p>\n<h3>\u5355\u4e00\u8fdb\u7a0b<\/h3>\n<p>\u5728\u8bbe\u5b9aCPU\u4e0a\u965016%\u53ca\u5185\u5b5816M\u4e0a\u9650\u4e4b\u540e\uff0c\u7ed3\u679c\u5982\u4e0b\uff1a\n<img decoding=\"async\" src=\"https:\/\/blog.dynox.cn\/wp-content\/uploads\/2023\/04\/winjob-cpu-1proc.png\" alt=\"CPUStress single process\" \/>\nexamples\/job_object.go\u6309\u5982\u4e0b\u4fee\u6539\uff1a<\/p>\n<pre><code class=\"prettyprint\" class=\"language-go\">var limits = []winjob.Limit{\n        winjob.WithBreakawayOK(),\n        winjob.WithKillOnJobClose(),\n        winjob.WithActiveProcessLimit(3),\n        winjob.WithProcessTimeLimit(10 * time.Second),\n        winjob.WithCPUHardCapLimit(1600),        \/\/ 16%\n        winjob.WithProcessMemoryLimit(16 &amp;lt;&amp;lt; 20), \/\/ 16MB\n        winjob.WithWriteClipboardLimit(),\n}\n\nconst defaultCommand = &amp;quot;.\\\\CPUStress.exe&amp;quot;<\/code><\/pre>\n<h3>\u591a\u8fdb\u7a0b(\u53cc\u8fdb\u7a0b)<\/h3>\n<p>\u5c06winjob.WithProcessMemoryLimit \u6539\u4e3a winjob.WithJobMemoryLimit\uff0c\u540e\u8005\u8868\u793a\u6b64job\u5185\u6240\u6709\u8fdb\u7a0b\u8981\u5360\u7528\u7684\u603b\u5185\u5b58\u9650\u5236\uff1a<\/p>\n<pre><code class=\"prettyprint\" class=\"language-go\">var limits = []winjob.Limit{\n        winjob.WithBreakawayOK(),\n        winjob.WithKillOnJobClose(),\n        winjob.WithActiveProcessLimit(3),\n        winjob.WithProcessTimeLimit(10 * time.Second),\n        winjob.WithCPUHardCapLimit(1600),    \/\/ 16%\n        winjob.WithJobMemoryLimit(16 &amp;lt;&amp;lt; 20), \/\/ 16MB\n        winjob.WithWriteClipboardLimit(),\n}<\/code><\/pre>\n<p>\u9a8c\u8bc1\u7ed3\u679c\u5982\u4e0b\uff1a\n<img decoding=\"async\" src=\"https:\/\/blog.dynox.cn\/wp-content\/uploads\/2023\/04\/winjob-cpu-2procsa.png\" alt=\"CPUStress 2-processes\" \/>\n<img decoding=\"async\" src=\"https:\/\/blog.dynox.cn\/wp-content\/uploads\/2023\/04\/winjob-cpu-2procsb.png\" alt=\"CPUStress 2-processes\" \/><\/p>\n<p>winjob example\u4ee3\u7801\uff1a<\/p>\n<pre><code class=\"prettyprint\" class=\"language-go\">\/\/ +build windows\n\npackage main\n\nimport (\n        &amp;quot;encoding\/json&amp;quot;\n        &amp;quot;log&amp;quot;\n        &amp;quot;os&amp;quot;\n        &amp;quot;os\/exec&amp;quot;\n        &amp;quot;os\/signal&amp;quot;\n        &amp;quot;time&amp;quot;\n\n        &amp;quot;golang.org\/x\/sys\/windows&amp;quot;\n\n        &amp;quot;github.com\/kolesnikovae\/go-winjob&amp;quot;\n)\n\nvar limits = []winjob.Limit{\n        winjob.WithBreakawayOK(),\n        winjob.WithKillOnJobClose(),\n        winjob.WithActiveProcessLimit(3),\n        winjob.WithProcessTimeLimit(10 * time.Second),\n        winjob.WithCPUHardCapLimit(1600),    \/\/ 16%\n        winjob.WithJobMemoryLimit(16 &amp;lt;&amp;lt; 20), \/\/ 16MB\n        winjob.WithWriteClipboardLimit(),\n}\n\nconst defaultCommand = &amp;quot;.\\\\CPUStress.exe&amp;quot;\nconst stressCommand  = &amp;quot;.\\\\CPUStressX64.exe&amp;quot;\n\nfunc main() {\n        job, err := winjob.Create(&amp;quot;&amp;quot;, limits...)\n        if err != nil {\n                log.Fatalf(&amp;quot;Create: %v&amp;quot;, err)\n        }\n\n        cmd := exec.Command(defaultCommand)\n        cmd.Stderr = os.Stderr\n        cmd.SysProcAttr = &amp;amp;windows.SysProcAttr{\n                CreationFlags: windows.CREATE_SUSPENDED,\n        }\n        if err := cmd.Start(); err != nil {\n                log.Fatalf(&amp;quot;Start: %v&amp;quot;, err)\n        }\n\n        stress := exec.Command(stressCommand)\n        stress.Stderr = os.Stderr\n        stress.SysProcAttr = &amp;amp;windows.SysProcAttr{\n                CreationFlags: windows.CREATE_SUSPENDED,\n        }\n        if err := stress.Start(); err != nil {\n                log.Fatalf(&amp;quot;Start: %v&amp;quot;, err)\n        }\n\n        s := make(chan os.Signal, 1)\n        signal.Notify(s, os.Interrupt)\n\n        c := make(chan winjob.Notification)\n        subscription, err := winjob.Notify(c, job)\n        if err != nil {\n                log.Fatalf(&amp;quot;Notify: %v&amp;quot;, err)\n        }\n\n        done := make(chan struct{})\n        go func() {\n                defer close(done)\n                ticker := time.NewTicker(time.Second * 5)\n                defer ticker.Stop()\n                var counters winjob.Counters\n                for {\n                        select {\n                        case &amp;lt;-s:\n                                log.Println(&amp;quot;Closing job object&amp;quot;)\n                                if err := job.Close(); err != nil {\n                                        log.Fatal(err)\n                                }\n                                log.Println(&amp;quot;Closing subscription&amp;quot;)\n                                if err := subscription.Close(); err != nil {\n                                        log.Fatal(err)\n                                }\n                                return\n\n                        case n, ok := &amp;lt;-c:\n                                if ok {\n                                        log.Printf(&amp;quot;Notification: %#v\\n&amp;quot;, n)\n                                } else if err := subscription.Err(); err != nil {\n                                        log.Fatalf(&amp;quot;Subscription: %v&amp;quot;, err)\n                                }\n\n                        case &amp;lt;-ticker.C:\n                                if err := job.QueryCounters(&amp;amp;counters); err != nil {\n                                        log.Fatalf(&amp;quot;QueryCounters: %v&amp;quot;, err)\n                                }\n                                b, err := json.MarshalIndent(counters, &amp;quot;&amp;quot;, &amp;quot;\\t&amp;quot;)\n                                if err != nil {\n                                        log.Fatal(err)\n                                }\n                                log.Printf(&amp;quot;Counters: \\n%s\\n&amp;quot;, b)\n                        }\n                }\n        }()\n\n        if err := job.Assign(cmd.Process); err != nil {\n                log.Fatalf(&amp;quot;Assign: %v&amp;quot;, err)\n        }\n        if err := winjob.Resume(cmd); err != nil {\n                log.Fatalf(&amp;quot;Resume: %v&amp;quot;, err)\n        }\n\n        if err := job.Assign(stress.Process); err != nil {\n                log.Fatalf(&amp;quot;Assign: %v&amp;quot;, err)\n        }\n        if err := winjob.Resume(stress); err != nil {\n                log.Fatalf(&amp;quot;Resume: %v&amp;quot;, err)\n        }\n\n        if err := cmd.Wait(); err != nil {\n                log.Fatalf(&amp;quot;Wait: %v&amp;quot;, err)\n        }\n        if err := stress.Wait(); err != nil {\n                log.Fatalf(&amp;quot;Wait: %v&amp;quot;, err)\n        }\n\n        \/\/ Wait for a signal.\n        &amp;lt;-done\n}<\/code><\/pre>\n<h2>\u53c2\u8003\u94fe\u63a5<\/h2>\n<ol>\n<li><a href=\"https:\/\/windowsreport.com\/limit-cpu-usage\/\">21 Best Ways to Limit the CPU Usage of a Process<\/a><\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/procthread\/process-and-thread-functions\">MSDN: Windows Process and Thread Functions<\/a><\/li>\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/procthread\/cpu-sets?source=recommendations\">MSDN: CPU Sets<\/a><\/li>\n<li><a href=\"http:\/\/blog.kalmbachnet.de\/?postid=28]\">GetThreadTimes<\/a><\/li>\n<\/ol><\/div>","protected":false},"excerpt":{"rendered":"<p>Windows\u81ea\u8eab\u6ca1\u6709\u63d0\u4f9b\u7c7b\u4f3cLinux cgroup\u7684\u80fd\u529b\u6765\u9650\u5236\u8fdb\u7a0b\u6216\u8fdb\u7a0b\u7ec4\u7684\u8d44\u6e90\u5360\u7528\uff0c\u8fdb\u7a0bCPU\/IO\/\u5185 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[9],"tags":[660,622,659],"views":109302,"_links":{"self":[{"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/posts\/1723"}],"collection":[{"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1723"}],"version-history":[{"count":1,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/posts\/1723\/revisions"}],"predecessor-version":[{"id":1724,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=\/wp\/v2\/posts\/1723\/revisions\/1724"}],"wp:attachment":[{"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.dynox.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}