Windows进程CPU、内存等资源限制

Windows自身没有提供类似Linux cgroup的能力来限制进程或进程组的资源占用,进程CPU/IO/内存/网络等资源的控制只能由自己实现。目前已有第三方的实现,主要是限制进程CPU的占用,如文档 < 21 Best Ways to Limit the CPU Usage of a Process > 所描述的BES,Process Tamer等软件。自Windows 8及Server 2012开始Windows系统有提供以job为单位的CPU占用及内存上限设置,之前的版本则只能以进程或线程为单位进行限制。

进程CPU占用限制方案

即时轮询系统所有进程(线程)的CPU占用,当发现所设定进程有超标时强制暂停进程所有线程的执行,然后在适当的时机再恢复执行。其中所涉及技术点:

进程CPU占用查询 GetProcessTimes

BOOL GetProcessTimes(
  [in]  HANDLE     hProcess,
  [out] LPFILETIME lpCreationTime,
  [out] LPFILETIME lpExitTime,
  [out] LPFILETIME lpKernelTime,
  [out] LPFILETIME lpUserTime
);

此函数可以获取进程从创建至当前的总运行时间及总的CPU时间,(KernelTime + UserTime) < 系统CPU数 * (当前时间 - CreationTime)

线程CPU占用查询 GetThreadTimes

BOOL GetThreadTimes(
  [in]  HANDLE     hThread,
  [out] LPFILETIME lpCreationTime,
  [out] LPFILETIME lpExitTime,
  [out] LPFILETIME lpKernelTime,
  [out] LPFILETIME lpUserTime
);

QueryThreadCycleTime可以提供更精准的CPU时间数据,单位为CPU时钟周期

BOOL QueryThreadCycleTime(
  [in]  HANDLE   ThreadHandle,
  [out] PULONG64 CycleTime
);

线程暂停及恢复

Windows平台没有提供暂停整个进程的支持函数,只能以线程为单位来操作,即SuspendThread及ResumeThread:

DWORD SuspendThread(
  [in] HANDLE hThread
);
DWORD ResumeThread(
  [in] HANDLE hThread
);

CPU亲和性设置: SetProcessAffinityMask

BOOL SetProcessAffinityMask(
  [in] HANDLE    hProcess,
  [in] DWORD_PTR dwProcessAffinityMask
);

此函数可以限定进程及其所有线程所能使用的CPU,故一定程序上亦限定了进程最大的系统CPU占用率。

DWORD_PTR SetThreadAffinityMask(
  [in] HANDLE    hThread,
  [in] DWORD_PTR dwThreadAffinityMask
);

此函数可单独限制特定线程的CPU亲和性。

进程优先级设置: SetPriorityClass

优先级解决的是优先运行及退让CPU的问题,本质上并不能限定CPU占用,只是优先级高于当前任务的忙碌的时候,当前进程会主动退让CPU 线程优先级设置:SetThreadPriority

BOOL SetThreadPriority(
  [in] HANDLE hThread,
  [in] int    nPriority
);

Job Objects

Windows系统提供了Job的概念用以管理多个进程,可以限制Job对象内所有进程及期线程的CPU核心占用、CPU占用及内存分配上限等,均通过SetInformationJobObject来实现,具体的CPU限制由JOBOBJECT_CPU_RATE_CONTROL_INFORMATION管理,内存限制则由JOBOBJECT_EXTENDED_LIMIT_INFORMATION来管理。

BOOL SetInformationJobObject(
  [in] HANDLE             hJob,
  [in] JOBOBJECTINFOCLASS JobObjectInformationClass,
  [in] LPVOID             lpJobObjectInformation,
  [in] DWORD              cbJobObjectInformationLength
);

需要注意的是CPU占用设置只有Windows 8及Server 2012之后的版本有效。

CPU Sets

此部分只限定了CPU Affinity属性

实验验证

可以直接利用开源项目go-winjob验证,验证系统Windows 8 x64,go-winjob git repo: https://github.com/kolesnikovae/go-winjob

验证程序

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void main(int argc, char *argv[])
{
        unsigned long total = 0, count = 0, i = 0;

        while (1) {
                if (malloc(1024)) {
                        total += 1024;
                        count++;
                }
                if (!(++i &amp; 4095))
                        printf(&quot;alloc: %u size: %u bytes\n&quot;, count, total);
    }
}

无限制

在无限制的情况下,此进程会占满一个CPU核心,commit内存总占用达2G CPUStress unlimited

单一进程

在设定CPU上限16%及内存16M上限之后,结果如下: CPUStress single process examples/job_object.go按如下修改:

var limits = []winjob.Limit{
        winjob.WithBreakawayOK(),
        winjob.WithKillOnJobClose(),
        winjob.WithActiveProcessLimit(3),
        winjob.WithProcessTimeLimit(10 * time.Second),
        winjob.WithCPUHardCapLimit(1600),        // 16%
        winjob.WithProcessMemoryLimit(16 &lt;&lt; 20), // 16MB
        winjob.WithWriteClipboardLimit(),
}

const defaultCommand = &quot;.\\CPUStress.exe&quot;

多进程(双进程)

将winjob.WithProcessMemoryLimit 改为 winjob.WithJobMemoryLimit,后者表示此job内所有进程要占用的总内存限制:

var limits = []winjob.Limit{
        winjob.WithBreakawayOK(),
        winjob.WithKillOnJobClose(),
        winjob.WithActiveProcessLimit(3),
        winjob.WithProcessTimeLimit(10 * time.Second),
        winjob.WithCPUHardCapLimit(1600),    // 16%
        winjob.WithJobMemoryLimit(16 &lt;&lt; 20), // 16MB
        winjob.WithWriteClipboardLimit(),
}

验证结果如下: CPUStress 2-processes CPUStress 2-processes

winjob example代码:

// +build windows

package main

import (
        &quot;encoding/json&quot;
        &quot;log&quot;
        &quot;os&quot;
        &quot;os/exec&quot;
        &quot;os/signal&quot;
        &quot;time&quot;

        &quot;golang.org/x/sys/windows&quot;

        &quot;github.com/kolesnikovae/go-winjob&quot;
)

var limits = []winjob.Limit{
        winjob.WithBreakawayOK(),
        winjob.WithKillOnJobClose(),
        winjob.WithActiveProcessLimit(3),
        winjob.WithProcessTimeLimit(10 * time.Second),
        winjob.WithCPUHardCapLimit(1600),    // 16%
        winjob.WithJobMemoryLimit(16 &lt;&lt; 20), // 16MB
        winjob.WithWriteClipboardLimit(),
}

const defaultCommand = &quot;.\\CPUStress.exe&quot;
const stressCommand  = &quot;.\\CPUStressX64.exe&quot;

func main() {
        job, err := winjob.Create(&quot;&quot;, limits...)
        if err != nil {
                log.Fatalf(&quot;Create: %v&quot;, err)
        }

        cmd := exec.Command(defaultCommand)
        cmd.Stderr = os.Stderr
        cmd.SysProcAttr = &amp;windows.SysProcAttr{
                CreationFlags: windows.CREATE_SUSPENDED,
        }
        if err := cmd.Start(); err != nil {
                log.Fatalf(&quot;Start: %v&quot;, err)
        }

        stress := exec.Command(stressCommand)
        stress.Stderr = os.Stderr
        stress.SysProcAttr = &amp;windows.SysProcAttr{
                CreationFlags: windows.CREATE_SUSPENDED,
        }
        if err := stress.Start(); err != nil {
                log.Fatalf(&quot;Start: %v&quot;, err)
        }

        s := make(chan os.Signal, 1)
        signal.Notify(s, os.Interrupt)

        c := make(chan winjob.Notification)
        subscription, err := winjob.Notify(c, job)
        if err != nil {
                log.Fatalf(&quot;Notify: %v&quot;, err)
        }

        done := make(chan struct{})
        go func() {
                defer close(done)
                ticker := time.NewTicker(time.Second * 5)
                defer ticker.Stop()
                var counters winjob.Counters
                for {
                        select {
                        case &lt;-s:
                                log.Println(&quot;Closing job object&quot;)
                                if err := job.Close(); err != nil {
                                        log.Fatal(err)
                                }
                                log.Println(&quot;Closing subscription&quot;)
                                if err := subscription.Close(); err != nil {
                                        log.Fatal(err)
                                }
                                return

                        case n, ok := &lt;-c:
                                if ok {
                                        log.Printf(&quot;Notification: %#v\n&quot;, n)
                                } else if err := subscription.Err(); err != nil {
                                        log.Fatalf(&quot;Subscription: %v&quot;, err)
                                }

                        case &lt;-ticker.C:
                                if err := job.QueryCounters(&amp;counters); err != nil {
                                        log.Fatalf(&quot;QueryCounters: %v&quot;, err)
                                }
                                b, err := json.MarshalIndent(counters, &quot;&quot;, &quot;\t&quot;)
                                if err != nil {
                                        log.Fatal(err)
                                }
                                log.Printf(&quot;Counters: \n%s\n&quot;, b)
                        }
                }
        }()

        if err := job.Assign(cmd.Process); err != nil {
                log.Fatalf(&quot;Assign: %v&quot;, err)
        }
        if err := winjob.Resume(cmd); err != nil {
                log.Fatalf(&quot;Resume: %v&quot;, err)
        }

        if err := job.Assign(stress.Process); err != nil {
                log.Fatalf(&quot;Assign: %v&quot;, err)
        }
        if err := winjob.Resume(stress); err != nil {
                log.Fatalf(&quot;Resume: %v&quot;, err)
        }

        if err := cmd.Wait(); err != nil {
                log.Fatalf(&quot;Wait: %v&quot;, err)
        }
        if err := stress.Wait(); err != nil {
                log.Fatalf(&quot;Wait: %v&quot;, err)
        }

        // Wait for a signal.
        &lt;-done
}

参考链接

  1. 21 Best Ways to Limit the CPU Usage of a Process
  2. MSDN: Windows Process and Thread Functions
  3. MSDN: CPU Sets
  4. GetThreadTimes

122,273 条评论

  1. Hi! I know this is kinda off topic however ,
    I’d figured I’d ask. Would you be interested in trading links or maybe guest writing
    a blog article or vice-versa? My site addresses a lot of the same subjects
    as yours and I think we could greatly benefit from each other.

    If you might be interested feel free to send me an email. I look forward to hearing from
    you! Superb blog by the way!

  2. Народ кто ставит Задолбался я уже искать нормальную контору Искал долго, перепробовал кучу вариантов Короче, нашел наконец толковую контору — ставки на спорт бишкек онлайн лучший выбор Бонусы и акции каждый день В общем, жмите чтобы не потерять — мостбет казино [url=https://mostbet-qap.com.kg]мостбет казино[/url] Не ведитесь на лохотроны Перешлите тому кто тоже ищет нормальную контору

  3. Люди, помогите дельным советом. Ситуация реально критическая, Дети сильно напуганы происходящим, Никакие народные методы и таблетки из аптеки вообще не помогают пока чисто случайно не нашли проверенную медицинскую службу, и обеспечивает быстрый выезд специалистов со всем необходимым оборудованием. Уже через пару часов человек наконец-то пришёл в себя и уснул,

    В общем, если не хотите рисковать жизнью близкого человека, жмите на источник, чтобы случайно не потерять контакты вывод из запоя цена на дому [url=https://lechenie.vyvod-iz-zapoya-na-domu-voronezh-kmp.ru]https://lechenie.vyvod-iz-zapoya-na-domu-voronezh-kmp.ru[/url] Квалифицированная медицинская помощь на дому — это единственный реальный выход, обязательно перешлите этот пост тем, кто тоже сейчас находится в такой же критической ситуации!

  4. Лечение начинается с оценки клинической картины. Врач-нарколог проводит осмотр, при необходимости назначает обследование, ЭКГ, анализы, тест на употребление веществ, проверяет основные показатели, уточняет данные о принимаемых лекарствах, хронических диагнозах, аллергии, опыте кодирования и прошлых попытках остановиться. На этой основе назначается детоксикация: витаминно-минеральный раствор, средства для восстановления водно-солевого баланса, успокоительные препараты, нейропротекторы, кардиопротекторы, гепатопротекторы и другие медикаменты, которые улучшают самочувствие, поддерживают функции головного мозга, печени, сердца и нервной системы.
    Получить больше информации – [url=https://vyvod-iz-zapoya-v-lyubercah14-3.ru/]vyvod iz zapoya lyubercy[/url]

  5. Помогаем быстро перейти от консультации к конкретному плану: выезд, стационар или наблюдение.
    Детальнее – [url=https://vyvod-iz-zapoya-v-lyubercah14-4.ru/]vyvod iz zapoya cena[/url]

  6. Люди помогите советом Близкий человек уже несколько дней в запое Дети напуганы В больницу тащить страшно Короче, врачи приехали и поставили систему — вывод из запоя цена адекватная Сняли ломку и стабилизировали состояние В общем, не потеряйте контакты — вывод из запоя стоимость [url=https://lechenie-1mo.vyvod-iz-zapoya-na-domu-voronezh-jhg.ru]https://lechenie-1mo.vyvod-iz-zapoya-na-domu-voronezh-jhg.ru[/url] Вывод из запоя на дому — это реальный выход Перешлите тем кто в такой же ситуации

  7. Народ кто ставит То выплаты задерживают Денег слил на всяком говне Короче, нашел наконец толковую контору — mostbet с быстрыми выплатами Всё летает как часы В общем, смотрите сами по ссылке — бк мостбет [url=https://mostbet-qap.com.kg]https://mostbet-qap.com.kg[/url] Только mostbet реально рулит Перешлите тому кто тоже ищет нормальную контору

  8. Слушайте кто сталкивался Близкий человек уже несколько дней в запое Жена в истерике Нужна срочная помощь на дому Короче, единственное что вытащило из запоя — выведение из запоя на дому без последствий Поставили капельницу с детоксикационным раствором В общем, телефон и цены тут — вывод из запоя на дому [url=https://lechenie-1mo.vyvod-iz-zapoya-na-domu-voronezh-jhg.ru]вывод из запоя на дому[/url] Вывод из запоя на дому — это реальный выход Перешлите тем кто в такой же ситуации

  9. Беттеры отзовитесь А поддержка молчит как рыба Искал долго, перепробовал кучу вариантов Короче, работает стабильно и честно — mostbet с быстрыми выплатами Всё летает как часы В общем, сохраняйте себе — билет на футбол [url=https://mostbet-lxi.com.kg]билет на футбол[/url] Только mostbet реально рулит Перешлите тому кто тоже ищет нормальную контору

  10. Наркологическая помощь в Люберцах может проводиться на дому, амбулаторно или в стационаре клиники. Формат подбирает врач после осмотра пациента, оценки длительности запоя, количества алкоголя, возраста, наличия хронических заболеваний, психического состояния и возможных осложнений. Главный принцип медицинской работы — не просто вывести человека из состояния опьянения или похмельного синдрома, а стабилизировать организм, снизить риск срыва и начать лечение алкогольной зависимости.
    Получить дополнительную информацию – http://vyvod-iz-zapoya-v-lyubercah14-2.ru/

  11. If youreside in Ponte Vedra Beach and looking most dependable garage door repair near me, Wagmore Garage Doors is the real solution. They turned up same-day for a damaged springtime, tuned the opener, and left everything well balanced and whisper-quiet garage door repair

  12. Быстро собираем первичную информацию, оцениваем риски и предлагаем подходящий вариант обращения.
    Выяснить больше – [url=https://vyvod-iz-zapoya-v-statsionare-v-gelendzhike3.ru/]вывод из запоя в стационаре клиника геленджик[/url]

  13. Казань — город с уникальным характером, где минареты мечетей соседствуют с золотыми куполами православных храмов, а древние легенды органично вплетаются в ритм современного мегаполиса. Чтобы увидеть столицу Татарстана во всем ее многообразии и не упустить важные детали, стоит довериться профессионалам. Ниже мы разберем, где купить экскурсии в Казани, как правильно их выбрать и какие маршруты считаются самыми захватывающими.

    Где купить экскурсии в Казани: основные каналы
    [url=https://kazanland.com/ekskursii-iz-kazani/joshkar-ola]экскурсии по иннополису[/url]
    Выбор способа бронирования зависит от вашего бюджета, стиля путешествия и желания общаться с местными жителями.

    1. Официальные туристско-информационные центры (ТИЦ)
    Где: ул. Баумана, 49 (в арке колокольни Богоявленского собора) и в аэропорту «Казань».
    Это самый надежный вариант для тех, кто ценит гарантированное качество. Здесь можно бесплатно взять карту города, получить консультацию и сразу же оплатить сертифицированные туры. Цены здесь фиксированные, без скрытых комиссий.

    2. Специализированные агрегаторы экскурсий
    Именно по этим запросам туристы чаще всего ищут информацию в сети:
    [url=https://kazanland.com/]экскурсии казань официальный сайт[/url]
    заказать экскурсию в казани
    казань экскурсии
    Популярные платформы позволяют сравнить десятки предложений от частных гидов и агентств. Вы можете прочитать реальные отзывы, посмотреть фотографии маршрутов и забронировать место онлайн за пару минут. Это идеальный способ найти бюджетные групповые прогулки или уникальные авторские программы.

    3. Сайты местных турфирм
    Многие казанские компании имеют собственные сайты с удобным календарем бронирования. Если вы хотите заказать экскурсию по Казани заранее, еще до приезда в город, этот способ подойдет лучше всего. Часто при раннем бронировании на сайте предоставляются скидки.
    [url=https://kazanland.com/ekskursii-iz-kazani/joshkar-ola]экскурсии казань йошкар ола[/url]
    4. Стойки отелей и хостелов
    Консьерж-сервис есть практически в любой гостинице в центре. Удобство заключается в том, что вам никуда не нужно идти — достаточно спуститься на ресепшен. Минус — выбор обычно ограничен 2–3 стандартными маршрутами, а цена может быть выше из-за комиссии отеля.

    5. Частные гиды через социальные сети
    Если пролистать городские паблики ВКонтакте или локальные Telegram-каналы, можно найти предложения напрямую от жителей. Этот путь позволяет договориться об индивидуальном графике и нестандартной программе, но требует осторожности: всегда просите предоплату только через безопасную сделку площадки.
    [url=https://kazanland.com/sviyazhsk]экскурсия в свияжск из казани[/url]
    Казань: что посмотреть? Экскурсии на любой вкус

    Чтобы понять, какая программа вам ближе, определитесь с форматом. Вот самые популярные направления, отвечающие на запрос «интересные экскурсии по Казани»:

    Классика за один день (обзорная)
    Идеально для первого знакомства. Гид покажет главные символы города: Казанский Кремль с падающей башней Сююмбике и мечетью Кул-Шариф, пешеходную улицу Баумана, Старо-Татарскую слободу с ее расписными деревянными домами, озеро Кабан и театр имени Камала. Обычно такие туры включают дегустацию местного чая с чак-чаком.
    [url=https://kazanland.com/ekskursii-iz-kazani/joshkar-ola]экскурсия в йошкар олу из казани[/url]
    Тематические погружения

    Гастрономический тур. Казань официально признана гастрономической столицей России. На такой экскурсии вас проведут по лучшим заведениям национальной кухни, научат отличать эчпочмак от перемяча и расскажут секреты приготовления идеального кыстыбыя.
    Мистическая Казань. Прогулка по старинным особнякам с привидениями, купеческим усадьбам и местам силы. Вам расскажут о татарских духах (шурале и убыр), подземных ходах под Кремлем и проклятиях древних ханов.
    Кино-тур. По следам культового фильма «Елки», который снимали в Иннополисе и Свияжске, или других картин, запечатлевших виды столицы Татарстана.

    Поездки за пределы города
    Столица Татарстана — это лишь вершина айсберга. Самые впечатляющие впечатления ждут за городской чертой:

    Остров-град Свияжск. Древняя крепость, построенная войском Ивана Грозного за четыре недели. Сегодня это музей-заповедник с потрясающими фресками Успенского собора, входящего в список наследия ЮНЕСКО.
    Древний Болгар. Место принятия ислама Волжской Булгарией. Величественные руины, Белая мечеть, напоминающая индийский Тадж-Махал, и Музей болгарской цивилизации.
    Раифский монастырь. Самый известный мужской монастырь республики, расположенный в живописном лесу на берегу Раифского озера. Сюда едут ради умиротворяющей атмосферы и местной святыни — Грузинской иконы Божией Матери.

    Как выбрать гида и не прогадать: чек-лист

    Прежде чем окончательно заказать экскурсию в Казани, проверьте несколько моментов:

    Отзывы. Не ограничивайтесь звездочками. Прочитайте последние комментарии, обращая внимание на то, насколько живым был рассказ гида и соблюдался ли тайминг.
    Размер группы. Для глубокого погружения выбирайте мини-группы до 8 человек или индивидуальные туры. В больших автобусах на 40 мест часто плохо слышно аудиогид.
    Что включено в стоимость. Уточните, входят ли билеты в музеи (например, в Башню Сююмбике или Благовещенский собор), дегустации и транспортные расходы.
    Язык. Большинство программ проводится на русском, но в ТИЦ и крупных агентствах легко найти англоязычных или даже франкоговорящих специалистов.
    Логистика. Узнайте точное место встречи и входит ли трансфер от вашего отеля в цену.

    Маршрут одного дня: готовый план

    Если времени мало, вот проверенный сценарий интересной пешей экскурсии:

    Утро: Встреча у Спасской башни Кремля. Осмотр комплекса изнутри (мечеть Кул-Шариф, пушечный двор).
    День: Спуск к Дворцу земледельцев. Эта локация стабильно попадает в подборки «казань что посмотреть экскурсии» благодаря своей монументальной архитектуре, напоминающей Хофбург в Вене.
    Обед: Переход на улицу Баумана. Время на обед в одном из национальных кафе.
    Вечер: Прогулка вдоль набережной канала Булак, подъем на смотровую площадку центра семьи «Казан» (в форме гигантского котла) и завершение дня в Старо-Татарской слободе с чашкой травяного чая.

    Планируя визит в столицу Татарстана, выделите время на изучение не только парадных фасадов, но и тихих дворов. Именно там скрывается настоящая душа города, которую так любят показывать местные краеведы. Забронируйте свой идеальный маршрут, чтобы поездка оставила только теплые воспоминания.
    казань свияжск экскурсии
    https://kazanland.com/ekskursii-iz-kazani/joshkar-ola

  14. Здорова, народ Муж просто потерял себя Родственники не знают что делать Таблетки не помогают Короче, врачи приехали и поставили систему — вывод из запоя на дому с капельницей Поставили капельницу с детоксикационным раствором В общем, вся инфа по ссылке — сколько стоит вывод из запоя [url=https://lechenie-1mo.vyvod-iz-zapoya-na-domu-voronezh-jhg.ru]https://lechenie-1mo.vyvod-iz-zapoya-na-domu-voronezh-jhg.ru[/url] Не ждите пока станет хуже Перешлите тем кто в такой же ситуации

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注