# Research on Multimedia Class Scheduler Service (MMCSS)



## Timecard

Got a lot more research coming later this week which will outline a bunch more of the operating aspects of MMCSS that isn't documented or published, so stay tuned.


----------



## Timecard

As promised and again *Originally shared on my Github*


https://github.com/djdallmann/GamingPCSetup/tree/master/RESEARCH/WINSERVICES#multimedia-class-scheduler-service-mmcss



*Q: What does the hidden MMCSS Latency Sensitive registry key actually do? What is the default value?*
Latency Sensitive refers to Latency Sensitive Hints, essentially under cpu heavy conditions MMCSS can create latency sensitive hints to the processor power performance engine to help adjust performance state (PoLatencySensitive). When this condition occurs we see *TurboEngaged* events in MMCSS provider event audit and corresponding Latency Sensitive Hints from SYSTEM in the Windows Kernel Power Provider.
Findings and Analysis

Latency Sensitive refers to Latency Sensitive Hints, essentially under heavy cpu use MMCSS can create latency sensitive hints to the processor power performance engine to help adjust performance state (PoLatencySensitive). When this condition occurs we see *TurboEngaged* events in MMCSS provider event audit and corresponding Latency Sensitive Hints from SYSTEM in the *Windows Kernel Power Provider.*










The *default value of Latency Sensitive is TRUE* at least on Windows 10, in order to set this to FALSE in MMCSS globally it must be added to all tasks.
Adjusting the values in the hidden power plan settings increases the frequency of those Latency Sensitive Hints for MMCSS tasks by lowering the threshold and response for those scenarios. The documentation and impact of changing these settings seems sparse so I cannot recommend changing these values at this time but it is noteworthy, these settings impact the entire system. On a similar note the Client/Server Runtime Subsystem (CSRSS) process is continually generating latency sensitive hints on my computer likely since its performance is directly tied to user experience and many components on the windows system including raw input interface between kernel and user space for mouse and keyboard. There also appears to be different types of Latency Sensitive Hint Types according to the event trails.
To unhide those values in the current power plan:
powercfg -attributes SUB_PROCESSOR 619b7505-003b-4e82-b7a6-4dd29c300971 -ATTRIB_HIDE
powercfg -attributes SUB_PROCESSOR 619b7505-003b-4e82-b7a6-4dd29c300972 -ATTRIB_HIDE

Related Power Options:

PerfLatencyHint
Registry Key Path:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MultiMedia\systemprofile\Tasks\<TASKNAME>\
String Value: Latency Sensitive
Values: True or False


*Q: Does the MMCSS task Clock Rate registry setting do anything?*
Firstly no, I haven't found any evidence that this setting has any impact which aligns with Microsofts Documentation but it can... yes I know very click baity. See findings and analysis for more information.
Findings and Analysis

During my tests of manipulating the Clockrate MMCSS task registry value it had no impact on MMCSS cycles, timer resolution or anything else I could think of at the time, Microsofts documentation states specifically *Starting with Windows 7 and Windows Server 2008 R2, this guarantee was removed to reduce system power consumption.* which seems to align with everything I checked.
There is one issue though which actually applies to MANY of the MMCSS task registry settings and parent keys, and that is *if you set a value too high (above 10,000 the default in this case), too low (~2,000, not sure of exact range tried a few) that MMCSS task will cease to function* while others will continue to work and receive boosts, this effectively creates a way of having MMCSS run while blocking certain MMCSS tasks. I will make a specific entry in this research page for other settings, examples and what impacts it could have.
On the last bullet point, this might explain why people say they can feel a difference changing the Clock Rate registry setting and that is because the MMCSS task completely ceases to function.
*Q: What is the BackgroundPriority mmcss registry setting? Does it have anything to do with the Background Only registry key?*
The BackgroundPriority registry key influences the *Base Thread priority* when the *Scheduling Category is Low*, and has no direct relation to the Background Only registry key. See findings and analysis for more information.
Findings and Analysis

During my analysis of different MMCSS tasks Audio and Pro Audio, the Background Only registry key value (True or False) had no direct relationship to the BackgroundPriority value.
When the *Scheduling Category is LOW, the base priority of the thread is not influenced by the tasks Priority setting*. When set to LOW the thread has a base value of 8, incrementing BackgroundPriority (default is 1) will boost the base priority giving you a maximum base priority of 15 (just before REALTIME 16 priority class).
*Thread Base Priority to BackgroundPriority Mapping*

BackgroundPriorityThread Base Pri1829310411512613714815
As noted above, this only applies when Scheduling Category is LOW.


*Q: Does the hidden MMCSS SystemProfile registry setting LazeModeTimeout alter the running state?*
Yes, this value does in fact alter the settings in the MMCSS Scheduler sleep cycle for idle time periods related to the events *IdleDetectionLazy* and *SleepRealtimeLazy*.
Findings and Analysis

This one was pretty easy to confirm, I changed the value then compared it to what MMCSS event provider was recording. This value alters the lazy sleep timeout periods globally, more information on what impact this has on the MMCSS scheduler in another MMCSS research article.








*Q: Does the hidden MMCSS SystemProfile registry settings MaxThreadsTotal and MaxThreadsPerProcess restrict overall use of MMCSS?*
Unfortunately this has zero impact on how many threads total or per process that could register with MMCSS during multiple tests, see findings for more information.
Findings and Analysis

For the evaluation of these settings I set each to different combinations of 1 and 3 (e.g. 3&1, 1&3, 3&3, 1&1) then I proceeded to generate MMCSS tasks for both Pro Audio and Audio, both separately and together. The simplest way to generate multiple threads for under a single process *under normal circumstances* is to open a browser such as Chrome then load a bunch of YouTube videos let's say 6 and ensure they are all playing media simultaneously, and in this scenario it had no impact on the number of threads registered to MMCSS under the Chrome browser process in relation to *MaxThreadsPerProcess*setting.
Its hard to say if this particular test is ideal but it was the quickest way to test, the reason being is that Chrome is a single parent process but for each tab child processes are created. Perhaps if it was a single parent process and I tried registering multiple threads in that process it may change the outcome.
I don't feel like writing custom code to test but if someone's interested in recreating the test and capturing the result please let me know.

A similar test was done however in relation to *MaxThreadsTotal*, the assumption of this setting is to globally restrict the total amount of threads that can register with MMCSS, in all tests the total threads registered in MMCSS were not restricted in those scenarios.

*Q: Does the MMCSS task registry setting SFIO Priority actually change the IO Priority or does it do nothing like Microsoft's documentation states?*
Microsoft's documentation is spot on again, the value of this registry setting does not influence IO Priority of the MMCSS registered thread.
Findings and Analysis

Microsofts documentation for MMCSS states the following and is again it's spot on.
SFIO Priority REG_SZ The scheduled I/O priority. This value can be set to Idle, Low, Normal, or High. *This value is not used.*

To test if this value had any impact I changed the setting for each scenario to one of the expected values *Idle, Low, Normal, and High* and ensured that MMCSS driver was restarted to re-read the new configuration from the registry. Kicked off a new capture of the MMCSS provider and launched some multimedia applications then let it run for a bit and stopped the capture. With the multimedia applications still running I reviewed the MMCSS provider information and found the associated Thread ID and analyzed the associated thread properties using Microsoft Windows Sysinternals Process Explorer and *observed that the IO Priority was not influenced in any scenario*.

*Q: How does MMCSS map the defined priorities and scheduling category in relation to the values recorded by the event provider?*
When a thread joins MMCSS it reads the registry for the specified tasks and maps those values to three different priority levels *Medium, Low and Uber Low* under the given Scheduling Category. For more information see findings and analysis, and associated priority mapping table reference.
Findings and Analysis

Based on those values (*Medium, Low and Uber Low*) and the scheduling category MMCSS has it's own internal mapping which is reflected in the boosted priority and a deprioritization value. The *Medium value reflects the boosted value* give or take +1 (not exactly intuitive but probably done this way for a reason, you'll see..) , the *Low value only applies for Scheduling Category Low* then *Uber Low reflects the deprioritzation value.*

The values are pretty consistent between the Scheduling Category Medium and High as you'll note when analyzing the table below. However when the scheduling category is Low things aren't exactly as they seem and I have seen some variation in the outcome which I'll note below. *When using Low the process is never deprioritized*, this is likely because the kernel will typically handle processes priority management outside of the realtime range (16+), on the same note only the processes intial priority value is set and *not boosted again*, at least during my analysis.
*Scheduling Category: High*

Intended range: 23-26
Actual range: 26


Conf. PriorityMedium PriLow PriUber Low PriMMCSS Boost PriMMCSS Deprioritization8248726772486267624852675248426642483265324822642248126312481262
*Scheduling Category: Medium*

Intended range: 16-22
Actual range: 17-23


Conf. PriorityMedium PriLow PriUber Low PriMMCSS Boost PriMMCSS Deprioritization8238723772286237621852265208421541983204318821932178118211681171
*Scheduling Category: Low*

Intended range: 8-15
Actual range: *It depends..*, see both tables and narrative


Conf. PriorityMedium PriLow PriUber Low PriMMCSS Boost PriMMCSS Deprioritization88878None78868None68858None58848None48838None38828None28818None18818None

With Scheduling Category set as Low I recevied two different results when comparing for example audiodg and Chrome, Chrome's task (Pro Audio) base priority never changes from 10 regardless of settings so this is likely due to the way the application was coded. However audiodg will use the default base priority of 8 using the *normal Priority* values, and then *only using Background Priority will it actually boost the base priority* as indicated below.
*Scheduling Category: Low and Background Priority*

Intended range: 8-15
Actual range: 8,9,11-15


Conf. BG PriorityMedium PriLow PriUber Low PriMMCSS Boost PriMMCSS Deprioritization888815None788714None688613None588512None488411None38839None28828None18818None


*Q: Does the MMCSS AlwaysOn registry setting exist?*
Yes, there does appear to be an MMCSS *AlwaysOn* registry setting in *both Windows 7 and Windows 8* but it does not exist in Windows 10. This may related to the fact that MMCSS is a driver in Windows 10 where as it is a service integrated in svchost.exe on older versions. The purpose of this registry key is currently unknown, if anyone has any evidence of its impact and use let me know.


*Q: What's actually happening inside MMCSS on a millisecond time scale? What variables are there and how do they come into play?*
There's a handful of events that are happening inside MMCSS, here's a breakdown of those events:

*Thread Joins* - Occurs when a thread registers with MMCSS and indicates which task it selected
*Scheduler Priority Change* - Priority is increased or decreased
*TaskIndex_PreDeadlineExpired* - Indicates a yield deadline has expired, occurs just before Scheduler Wakeup
*Scheduler Wakeup* - Occurs when a yield deadline is reached
*Scheduler Sleep* - Indicates when the scheduler sleeps, the type of sleep and duration.
*Set_MultimediaMode and Thread Buffering* - Likely signals kernel streaming
*TaskIndex_Yield* - Summarizes the yield period duration
To learn more about MMCSS behavior, potential gotchas, and variables then see findings and analysis.
Findings and Analysis
To explain what MMCSS is doing it's best to use an example so in this case we'll assume the following:

We have a *default MMCSS system profile and task settings*
Using the Chromium based Microsoft Edge browser we'll play a YouTube video
*Note:* audiodg.exe is required for media playback so it'll always have a thread join event as a result *there will always be a minimum of 2 mmcss task threads* in most circumstances.




In the following table time represents the actions performed during each millisecond:

TimeEventDescription1msMMCSS Initialization of first registered threadsN/A1msThread JoinsA MMCSS Pro Audio task is registered (Index00001 - msedge.exe)1msScheduler Priority ChangeMMCSS boosts the thread (Index00001 - msedge.exe) to the defined value in Pro Audio e.g. Sched Cat: High, Pri: 2, Priority 26 (Realtime)1msScheduler WakeupReturns from a *DeepSleep state*1msScheduler SleepEnters the realtime sleep state1msThread JoinsA MMCSS Audio task is registered (Index00002 - audiodg.exe)1msScheduler Priority ChangeMMCSS boosts the thread (Index00002 - audiodg.exe) to the defined value in Audio e.g. Sched Cat: Medium, Pri: 6, Priority 22 (Realtime)2msSet_MultimediaMode (1 then 0), Thread Buffering (Start then Stop)Toggles two functions briefly, usually only seen upon initialization of MMCSS2msTaskIndex_YieldTaskIndex Index00002 (audiodg.exe) has yielded for X2msScheduler Priority ChangeDeprioritizes task TaskIndex Index00002 (audiodg.exe) to 16.[...]*~10ms passes*The thread yields and service is in an Idle detection sleep state, *when this happens only audiodg.exe is boosted* 22 to 16, 16 to 22 (Audio Task)11msScheduler Priority ChangeMMCSS boosts the thread (Index00002 - audiodg.exe) to 2211msTaskIndex_PreDeadlineExpiredTaskIndex Index00002 (audiodg.exe) predeadline has passed.11msScheduler WakeupNew thread yield deadline12msTaskIndex_YieldTaskIndex Index00002 (audiodg.exe) yield complete12msScheduler Priority ChangeDeprioritizes task TaskIndex Index00002 (audiodg.exe) to 16.[...]*~10ms passes*Yield and Idle detection22msScheduler Priority ChangeMMCSS boosts the thread (Index00002 - audiodg.exe) to 2222msTaskIndex_PreDeadlineExpiredTaskIndex Index00002 (audiodg.exe) predeadline has passed.22msScheduler WakeupYield Deadline23msTaskIndex_YieldTaskIndex Index00002 (audiodg.exe) yield complete23msScheduler Priority ChangeDeprioritizes task TaskIndex Index00002 (audiodg.exe) to 16.[...]Cycle repeatsIf Idle Detection identifies activity. *When tasks priorities are updated they are done in the order of the index* e.g. 00001, 00002, 00003.200msIdle detectionFinally realizes you're there and begins prioritizing things according to *SystemResponsiveness*200msScheduler Priority Change*Deprioritizes* each tasks based on their config mapping200msScheduler SleepIdleDetection (Default 10ms) or IdleDetectionLazy (Default 100ms), will explain this after202msScheduler WakeupYield Deadline202msScheduler Priority Change, *2ms passes**MMCSS boosts priority of all mmcss threads*, also *note 2ms has passed* during the deprioritized state and that systemresponsiveness is 20 by default, e.g. 2ms and 8ms[...]*8ms passes* in a boosted stateN/A210msScheduler Priority ChangeDeprioritizes each tasks based on their config mapping210msScheduler SleepIdleDetection (Default 10ms) or IdleDetectionLazy (Default 100ms)211msScheduler WakeupYield Deadline211msScheduler Priority ChangeMMCSS boosts all the threads[...]Cycle repeats*If you are detected as not Idle all task threads boost*, otherwise if idle state is detected only audiodg.exe is boosted like in the beginning, more details on Idle detection below
And there you have it, a general overview of what happens inside MMCSS and now we get into IdleDetection and IdleDetectionLazy...

*Idle Detection and IdleDetectionLazy*
Idle detection doesn't seem to work the way you think it might, it doesn't appear to be based on the fact that you're constantly playing media but perhaps related to other methods such as user input or indicators.

Based on my analysis this is how IdleDetection works and how it can get into similar states where no mmcss prioritization occurs** although the user is actively playing game or playing media. First off *IdleDetection* is done roughly on 10ms periods (value 100,000, *100 nanosecond intervals*) and if it doesn't detect any activity it shifts into *IdleDetectionLazy* mode which operates at 100ms periods (value 1,000,000, 100 nanosecond intervals). When activity isn't detected *on* the 100ms interval, it goes into another 100ms period which seems to easily chain into many lazy cycles for *20 seconds or more* leaving threads in a potentially *suboptimal state*. When IdleDetectionLazy occurs only audiodg.exe is prioritized and deprioritized as indicated above.

Luckily you can alter how MMCSS IdleDetection and IdleDetectionLazy states operate by fine tuning a few hidden variables, *NoLazyMode and LazyModeTimeout*. NoLazyMode will outright disable IdleDetection for the most part however it *may* be more resource intensive, alternatively you can change the LazyModeTimeout 100ns interval by adding and setting the hidden registry key value.

LazyModeTimeout Default: 1,000,000 (100ms), is a 100 nanosecond interval.
Optimized: 10,000 (1ms)
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MultiMedia\systemprofile\LazyModeTimeout DWORD (32bit) : 10000

NoLazyMode Default: 0 (Off)
Optional: On
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MultiMedia\systemprofile\NoLazyMode DWORD (32bit) : 1

*List of values for scheduler sleep:*

SleepRealtimeLazy: 1,000,000 (100ms)
IdleDetectionLazy: 1,000,000 (100ms)
IdleDetection: 100,000 (10ms)
Realtime 80,000 (8ms)
SleepResponsiveness 20,000 (2ms)
DeepSleep: 4,294,967,295
*System Responsiveness*
After having gone through the example above you may note that this setting is a literal translation of time, *2ms (20) for low priority tasks* and *8ms, the remainder* for mmcss registered tasks in their boosted priority states when using the default systemresponsiveness setting. On that note you should also keep in mind those same threads are still using quite a bit of cpu time in a lower priority state but... when the threads are below priority 16 (realtime) the kernel can give more attention to those other threads by shifting their priorities as needed.


----------



## Timecard

*Q: What happens when you set SystemResponsiveness to a value higher than 50?*
When MMCSS SystemResponsiveness is set to values above 50 (e.g. 60, 70, 80 & 90) audiodg.exe will register a thread with MMCSS and leave immediately after, following this only the games registered thread will be boosted. Thank you plumch who reported this on discord.


*Q: Can you set SystemResponsiveness to 100?*
Setting SystemResponsiveness to 100 on Windows 10 MMCSS essentially disables the service preventing it from starting.


----------



## Marios145

Man, this is pure gold. Thanks for all the time you put into this research.


----------



## Timecard




----------



## empl

Thanks for re-posting. Great article!

Can you specify: how do I start a trace for the *Microsoft-Windows-MMCSS ETW trace provider* ?

In Microsoft documentation these are only options for parameter of xperf *-providers*:









providers


providers



docs.microsoft.com





Second link for authoring custom recording profiles requires to Install Visual Studio. I would rather not. 

Thanks.


----------



## Timecard

Put this in a file, call it something like mmcss.wprp and import it into WPR.



Code:


<?xml version="1.0" standalone='yes'?>
<WindowsPerformanceRecorder
  Version="1.0"
  Author=""
  Team=""
  Comments=""
  Company="Microsoft Corporation"
  Copyright="Microsoft Corporation"
  Tag="">
  <Profiles>
    <!-- Collector for system tracing -->
    <SystemCollector Id="SystemCollector" Name="System Collector">
      <BufferSize Value="2048"/>
      <Buffers Value="2048"/>
    </SystemCollector>
    <EventCollector Id="EventCollector-NonpagedPool" Name="Event Collector NonpagedPool">
      <BufferSize Value="2048"/>
      <Buffers Value="2048"/>
    </EventCollector>

    <SystemProvider Id="SystemProvider">
      <Keywords>
        <Keyword Value="Loader"/>
        <Keyword Value="ProcessThread"/>
      </Keywords>
    </SystemProvider>

    <EventProvider Id="Manifested/Microsoft-Windows-MMCSS" Name="36008301-e154-466c-acec-5f4cbd6b4694" Level="5" NonPagedMemory="true" Stack="true"/>

    <Profile Id="MMCSS.Verbose.File" LoggingMode="File" Name="MMCSS" DetailLevel="Verbose" Description="MMCSS">
      <Collectors>
        <SystemCollectorId Value="SystemCollector">
          <SystemProviderId Value="SystemProvider"/>
        </SystemCollectorId>
        <EventCollectorId Value="EventCollector-NonpagedPool">
          <EventProviders>
            <EventProviderId Value="Manifested/Microsoft-Windows-MMCSS"/>
          </EventProviders>
        </EventCollectorId>
      </Collectors>
    </Profile>

  </Profiles>
</WindowsPerformanceRecorder>


----------



## empl

Timecard said:


> Put this in a file, call it something like mmcss.wprp and import it into WPR.


Long story short: WPA was bugged on 2 clean installs, tried every permutation that exists and it showed it was Windows Color Profile set to sRGB virtual color profile, what caused crashes + even .Net Runtime error and application error OMEGALUL...

*EDIT 03/28: *Hmm nothing shows under MMCSS, not even audio! Specifically it doesn't register it to a game. I launched BF1 and nothing showed... And what concerns "Set_MultimediaMode" - I don't know what exactly is kernel streaming! I also I can't expand this category, there are no arrows. And if I expand process: System (4) I have like million things there!

And NoLazyMode is probably useless then, I don't have a lot of programs running in background so I guess that is useless. And latency sensitive, I don't use Turbo anyways and have CPU running in C0 state constantly in-game. Still interesting to know what it was for.

To add: I use process lasso, but it should still use MMCSS to override priorities etc. no?
*







*


----------



## xen64

So what settings should I use for gaming? I play twitchy FPS games like CS:GO, Valorant, Warzone, etc. I want the fastest responsiveness possible.

If I understand your information correctly I should set Audio tasks to the highest priority in the registry?


----------



## Timecard

Defaults are likely fine in any system, keep in mind its almost always the "audio" thread that gets more cpu since only that thread is boosted. With that said this means other game threads may be impacted perhaps positively or negatively due to the above.


----------



## Helder Magalhães

Timecard said:


> *Originally shared on my Github*
> https://github.com/djdallmann/Gamin...ICES#multimedia-class-scheduler-service-mmcss


Link is not correct (HTTP 404), although there are a few more links in the post that point to the proper content. The corrected link is:
GamingPCSetup/README.md at master · djdallmann/GamingPCSetup


----------



## Timecard

Yes I have since restructured my github, I'll fix soon.


----------



## ios1ph

First of all, I want to thank you for doing research in MMCSS. It is really great work!
And here comes my question.
A lot of "tweakers" add high priority to "games" in mmcss which is useless cause your research
proves that games like csgo use "audio".
Does this mean that putting high priorities on "audio pro" and "audio" will increase fps and reduce input latency? What do you think?
I have an external input lag tester based on Arduino and I am ready to test it out.
I mean, is it logically and theoretically can have an impact on fps or input lag.


----------



## Timecard

ios1ph said:


> Does this mean that putting high priorities on "audio pro" and "audio" will increase fps and reduce input latency? What do you think?


Keep in mind mmcss is typically "boosting" audio related threads, so you're really just giving more time to those activities which can impact other aspects of your multimedia experience. Audio processes quicker but at the same time takes time away from other threads since it's in real time priority for 8ms (by default with systrem responsiveness 20). See what works and feels best for you.


----------



## St1cky_

I think with "IdleDetectionCycles", you can influence the cycles. Default is 2.
And for "LazyModeTimeout" i got 64, maybe different Value on newest Build.

What is with SchedulerTimerResolution?
SchedulerTimerResolution = 10000

MaxThreadsPerProcess uses 32 as Default.


----------



## AndreyRGW

Is it possible to add some programs to the MMCSS scheduler, just like dwm and csrss?


----------



## Timecard

See DwmEnableMMCSS ^ you can test it with my power shell script.


----------



## AndreyRGW

Timecard said:


> See DwmEnableMMCSS ^ you can test it with my power shell script.


Yes, but as far as I know DwmEnableMMCSS is a function of dwmapi.h. But I'm talking about adding any programs to MMCSS. I tried writing a C# program that used AvSetMmMaxThreadCharacteristicsA to add any process to the MMCSS scheduler, but in the end it could only add itself to the MMCSS scheduler.


----------



## Timecard

Yep the calling thread needs to invoke it, so you're probably looking at hooking/injection to accomplish that.


----------

