This is an authoritative masterclass from the original creator that brilliantly clarifies the technical reality behind Windows system metrics. It is a rare privilege to see a complex OS mechanism explained with such insider precision and clarity.
Approfondir
Prérequis
- Pas de données disponibles.
Prochaines étapes
- Pas de données disponibles.
Approfondir
Task Manager is LYING About Your CPU Usage (Here's the Truth)Ajouté :
Hey, I'm Dave. Welcome to my shop. I'm Dave Plameumber, a retired operating systems engineer from Microsoft going back to the MS DOS and Windows 95 days.
And today we're going to find out how Task Manager actually measures your CPU usage. If you've ever looked at Task Manager and wondered why the numbers sometimes feel a little off, well, stick around. By the end of this video, you'll understand exactly what those percentages really mean and why they're not always what you think or would expect. But measuring CPU usage sounds like it ought to be one of the easiest jobs in computing. I mean, either the CPU is busy or it's not, right? It's silicon, not interpretive dance. So, surely you just ask Windows, "Hey, how busy are you?" and it tells you 73% and then we all go home early. Except almost none of that is true. Because the first uncomfortable question is busy doing what exactly? Busy on one core or all of them? Busy right now or averaged over the last second or two seconds or however often your UI happened to wake up. busy in user mode or kernel mode or interrupt time or deferred procedure calls or the idle loop or some weird accounting bucket that only exists because theuler needed somewhere to hand the bill. And once you start asking those questions, what looked like a simple speedometer starts looking more like forensic accounting. Now, of course, this one is fun for me because, as you likely know, I wrote the original task manager and Microsoft was kind enough to send my code over. So, today we can pop the hood open and look at how it actually did the job. The punch line is almost the opposite. It has to build a useful lie from a pile of true counters and statistics. The first thing to notice is that Task Manager is timerdriven. There's a refresh event and when that timer fires, it updates the process data and then repaints the list view. That sounds obvious, but it matters here because it immediately tells you something important. Task manager is not showing you an instantaneous property of the machine.
It is showing you a periodically refreshed interpretation of activity that happened between looks. That means the UI timer is the metronome for the display, but not for the CPU calculations. Of course, the CPU has no idea the task manager even exists. It just keeps executing instructions like a caffeinated squirrel in a copper maze.
And every so often, task manager peaks in through the window and tries to summarize the mayhem without actually disturbing the action. But here's the clever and subtle part. It does not trust the interval timer itself as the denominator. Because a less careful implementation might say, "Okay, 2 seconds elaps. Let's just divide every process's consumed CPU time by 2 seconds. But that would make the answer depend on the gooey timer firing precisely, which on Windows is already a little like trusting a metronome to stay perfectly steady while it's riding in the back of a pickup truck on a pothole filled dirt road. Instead, Task Manager asks the colonel for cumulative process execution times. Not how busy was this process right now, but how much total user plus kernel time has this process accumulated since it started going back to the beginning of time. And that's a huge conceptual difference. Why? Because what Task Manager gets back for each process is essentially an adometer, not a speedometer. Each process is a running total of user time it's used plus kernel time. And Task Manager compares that total to the last total it saw in the previous refresh. So for an individual process, the math essentially is the cumulative current CPU time minus previous cumulative CPU time. And that gives you how much CPU has been consumed by that process during the interval between the samples. Okay, so that part's straightforward enough. But now we need a denominator. And that's where this code gets interesting. Before it updates individual process entries, it does a first pass over the entire process table and sums everybody's cumulative times. The current totals go into total time and the previously remembered totals go into last total time. Then it subtracts the two to get a total delta for the entire system. That means the denominator is not whatever the refresh timer or thought elapsed and it's not even how long since the last update. The denominator is how much total CPU time was actually accounted for and consumed by all processes between the last sample and this one.
It's a much better answer and it's far more precise. If the UI got delayed a bit or the timer didn't wake up exactly when you hoped or the machine was busy, the numbers still come out sane because you're dividing the actual consumed process time by the actual consumed total wall clock time. Now the display may be late to actually show it, but the ratio remains meaningful. And then the per process percentage is just that process's delta divided by the total delta. If you look at the actual code in set CPU, it does the math with integer arithmetic. Now, if that looks like the sort of thing you write when you've been locked in an office too long with a copy of pets old and a lot of coffee, that's because it basically is. But there's method to the madness. It's just integer math arranged to produce a rounded percentage without having to drag any floating point into it through a very hot UI path. Very 1990s, very desktop utility, very I know exactly what the machine is going to do, and I'd like you to do that and only that, please. Now, speaking of the '90s, there's one wrinkle on modern machines that didn't really haunt the original Task Manager, and that's the fact that a CPU second of work no longer implies anything like a fixed amount of work. Back in the day, the scheduler's time accounting and the processor's actual throughput were much more tightly coupled because the CPU clocks were comparatively static. On the modern CPUs, though, the hardware is constantly changing gears. A mostly idle core may be downclocked, parked, or dropped into a state of sleep, sipping power through a cocktail straw, and then the instant that real work shows back up, it can jump up to a much higher frequency or even turbo past its nominal clock. Task manager's accounting is still fundamentally timebased, which means it is answering how long was this process scheduled in idle and not how many cycles did it actually get. So a core that was busy for half of the sample interval still shows about 50% CPU, even though the amount of work accomplished during that half can vary wildly depending on what frequency the silicon was running at. And that's where users quite reasonably get annoyed because what they actually experience is the performance and not the accounting.
They see one machine sitting at 25% CPU and feeling lightning fast, while another is pegged at 100% and it feels like it's trying to run Windows through molasses. The meter isn't wrong, but it's measuring sort of occupancy rather than productivity. Put differently, modern CPU usage is more like how full was the freeway rather than how many miles were actually traveled. A half full freeway with Ferraris on it can move a lot more traffic than a jam freeway full of old cement trucks. Now, the old task manager was built in an era where the time used was a pretty decent proxy for what work got done. But on today's processors with dynamic frequency scaling, turbo boost, thermal throttling, and deep idle states, that connection has gotten a lot looser. So, when the numbers feel a little slippery, it's not because the tool is broken so much as the hardware stops being simple enough for a single percentage to tell you the whole story. And then there's this little delicious detail. If the CPU computed percentage is greater than 99, it gets clamped back down to 99. This is what you would call version three of this assertion. And this line of code has an interesting backstory. Early in Task Manager's history, at exactly this point in the code, I was sometimes seeing numbers that added up to more than 100%. And that's just not possible if the math is being done right. And so I spent a lot of time staring at the math, making sure it was spot-on, because the only alternative was that there was a bug in the kernel. And to understand why that's a daunting prospect, you kind of have to understand the pecking order at Microsoft in the '90s. Because no matter what your title or role or rank, what mattered more to your fellow developers at least was what you were working on and how good you were at it. So if you were working on the CD edition of Microsoft Dogs, which was a real product, mind you, the performance bar for an amazing performance would be higher than if you were working on some serious systems code. And if you were on the system side, it was delineated even more precisely within. Because you see, I was a systems UI programmer. And yes, it's an essential service, and nobody likes it when the explorer crashes, but it's not the kernel. And the kernel is where the silverbacks live. People like Dave Cutler and Mark Lakovsky and Mark Zakowski, people with Wikipedia pages about their career history. And I was just a UI guy drawing little pictures of CPU usage. So, as you can imagine, when I proposed to the colonel guys that, hey, maybe it's your bug, they were what I would charitably call unsympathetic to my plate. And when I ran out of things to look at and staring at the code wasn't getting me anywhere, I started doing one of my favorite things as a developer, instrumenting my code with lots of asserts. Now, an assert is a statement you make in the code. And if the reality is any different, the code stops and asserts, which is to say, it throws a fault and it stops in the debugger so that you can inspect the machine to determine exactly why your assertion proved false. Imagine you were writing a civ to locate prime numbers.
You know that all primes are odd, at least over two. And so as an example, you might have code that asserts that the discovered prime is odd. Stuff like that. And then I added an assert to the code to enforce the limit that the total CPU usage should not exceed 100%. And I added multiple checks and asserts along the way as the number was being built up to make sure along the way as well. But it was a weird case that hardly ever happened and it never fired on my machine of course or on any of the machines of the other people on my team.
I needed more virtual eyeballs on this problem, and I needed really everybody's machine across the company keeping tabs on the total CPU and alerting me if things did not add up as expected. So, I did the one thing that I felt gave me the best odds of finding out if anybody hit this case. I put my name and home phone number in the assertion. That way, no matter who in the company hit it or when or where or in what building, they would be given my contact info and let me know about it. And still nothing.
Now, back in those days, Microsoft developers ate their own dog food, which is to say, we ran the latest stable build of Windows on our dev machines at all times. And as uncommon as the situation was, I was still surprised that I never got a lead. And then I kind of forgot about it for a while and I moved on down the bug list and worked on other features. And then we shipped the beta. Now, I don't know exactly how many people get the Windows beta, but if it's not millions of people, it's certainly many thousands of folks. And now they would all be armed with code that would display my home phone number in a dialogue if things went sideways. As I prepared to move to a new home in a different area code and to enter truck driving school as a backup career, something surprising happened. Nothing.
No one called. No one ever had until I mentioned it on YouTube a couple of years ago. Because you see, I still have the same home phone number some 30ome years later. And that assertion with my home phone number is still in every source code leak on the internet. So, if you run across the code and find my number, please shoot me an email instead. Long story short, we never got a useful assertion report from the field, but we eventually trapped it in a debugger on a lab machine, and the colonel developers were able to investigate it and confirm that it was in fact a rare accounting anomaly on the kernel side. And that yielded the two outcomes that I was hoping for. Wasn't my bug, and it was fixed. It's one of those tiny bits of old code that tells a story because out in the real world, measurements get messy. Timers wobble, races happen, multipprocessor accounting gets weird around the edges. But if the UI flashes to 103% on a single percentage column, users stop asking, hey, what's this subtle accounting defect? And they start asking, why is Windows drunk? Now, one of the biggest reasons users think Task Manager is lying to them is on multi-core machines.
And this is where the denominator choice matters enormously. Suppose you have an 8 core machine and one process pegs exactly one core flat out. A lot of people instinctively expect to see 100% in the graph because that's what it is from that process's view. It has the pedal to the floor using every sequential cycle it can get. But from the machine's point of view, it's only consuming 1/8 of the total available execution capacity. So task manager is going to show something like 12 or 13%.
That isn't a bug. It's just a particular worldview. Task manager's process CPU column is answering the question, what share of total machine CPU capacity did this process consume during the sample window. It is not answering how hard did this process work relative to the one thread that it happened to own. Those are very different questions and if you ask the wrong one of the right tool, you'll get mad at the mirror. And it gets even better because the system idle process is accounted for in there too.
Historically, idle time was represented by a pseudo process called idle, which is just one of those operating system jokes that sounds absurd until you realize that it's incredibly useful.
Unused CPU or idle CPU isn't nothing, it's accounted nothing. The machine needs a bucket for theuler had absolutely nothing better to do. And so, the idle process becomes the cosmic waste basket into which all unclaimed cycles are swept. That means the percentages add up sensibly. Busy processes plus idle time gives you the total. And if one process uses 25% and the idle process uses 75%, that machine was a quarter busy over that interval.
Nice, clean, and honest, but it's not instantaneous. And that part matters, so it's worth sitting on that for a minute.
The CPU number in Task Manager is a moving little obituary for the immediate past. It tells you what just happened over the last refresh window, not what happened at the moment that your eyeballs landed on the row. If the process wakes up, goes berserk for 100 milliseconds, and then goes back to sleep. Task manager may show a small average or even a rounded zero depending on the refresh window and how much total capacity existed during that interval.
That's not because it missed or didn't see the work. It's because it diluted the work over that whole window. And this is why CPU usage can sometimes feel misleading. Not wrong, just averaged.
Like trying to describe a car chase on YouTube by reporting the average speed from the driveway to the courthouse.
Technically correct, but emotionally useless. The reality is that with multi-core machines, you either have to watch individual CPU graphs to get a sense of individual load or just live with the fact that a single core process might be maxed out while your other cores are just sitting there. The code also has to deal with a bunch of ugly real world corner cases that tell you that measuring CPU is not a pristine science experiment. For example, if a process's cumulative CPU time appears to go backwards, the code has to assume that the process ID has probably been reused and so it invalidates the old process object. It's one of those cosmic coincidence things, but it could happen.
And so the code must assume it's possible. And that's a great example of the difference between theory and actually shipping software. In theory, process time should never decrease, but in practice, processes die. PIDs get reused. And if you naively associate PID 1 2 3 4 right now with PID 1 2 3 4 from the last refresh, you can wind up comparing one process's little tombstone with another process's birth certificate. And so the code defensively throws that old entry out and starts fresh. Otherwise, you could wind up with a process actually reporting negative CPU usage. There's also a special case for the idle process having zero time, which gets invalidated as bogus because again, it can't be exactly zero because you're not dealing with laboratory glassware here. You're dealing with live operating system state mid-stride while that horse is still running. And then we get to one of my favorite little weird corners of this file. Wow tasks. Wow stands for Windows on Windows. And it was the way that 16-bit Windows 3.1 apps could run on NT. There was one master process in 32-bit called NTVDM. And then it in turn managed all of the 16-bit tasks that were under its control. Now, if you want proof that CPU accounting is sometimes interpretation as much as measurement, there it is. The code actually has to cap the sum of the child task times so they don't exceed the parent of NTVDM's total because the thread times are gathered later and can otherwise overrun the parents reported total. In other words, even with real counters, the moment you start attributing work across abstraction boundaries, the books stop balancing automatically. And that's the whole game. Assume nothing, assert everything.
Now, CPU usage is not a substance that exists in a vial somewhere. It's a ratio built from accounting decisions. What counts as process time? What counts as kernel work on behalf of a process? What counts as truly idle and over what window do we average? Do we show one core saturation or total machine share?
Do we round? Do we clamp? Do we smooth?
Do we favor responsiveness over numeric stability? Every system monitor from top to task manager answers those questions via its implementation whether it admits it or not in the help file. Now, Task Manager's approach was cheap, fairly robust, and understandable enough for normal humans, which actually matters because a performance tool that requires a graduate seminar before breakfast has already lost the room. There's a reason we're not all rocking Windows Perfmon.
But it also means you need to know what you're looking at. Like, I've got a monster Dell 7875 precision workstation here with 192 thread cores. It means that if one of them is completely pegged on a process, it would still be 99% idle. And in a more common case, if you see 12% on a more pedestrian machine, that may still be one core near melting.
If you see 0%, that may mean less than 1% averaged over the sample window and not absolutely no work happened. If you see a process bounced between 0 and six and 0 and 12, it's probably like a bursty worker thread doing exactly what it should. And to be fair, if you're using task manager to try and catch a micro stutter or a scheduleuler hiccup or a DPC storm with a 1se secondond UI average, you're kind of using a butter knife as a screwdriver. useful tool but wrong forensic expectation. And that to me is the interesting lesson in old code like this. We often imagine that the old utilities are somehow more pure and honest because they were closer to the metal. And in a sense they were. But what they really were was explicit. You can see the little lie being built up.
You can see the choices. You can see the compromises between truth, cost, simplicity, and what would actually fit on the screen without making the list view flicker like a haunted jukebox. And just for fun, here's the Windows NT4 Task Manager running on Windows 11 with 192 CPUs. Yes, it works, but it rounds CPU cores into groups of 16 since that time nobody ever seen a machine with more than four cores anyway. So, I had to pick what to do with them. And I decided to group them in groups of 16.
Still, I think it speaks well to the code, not to mention Windows relentless backward compatibility that it still works out of the box today. I actually love that because once you understand it, Task Manager stops being that thing that sometimes lies about CPU and becomes something much more respectable.
A very fast, very cheap, very human readable approximation of a complicated reality. It may not be the perfect number, but it's the number that felt the most honest and useful to me one Tuesday morning in 1995. And like Drago, I was programming for me that day.
the truth.
>> And honestly, that's most of systems programming. Not finding the perfect truth, but finding the cheapest, honest summary that helps a user make a good decision before lunch. And so the next time somebody says CPU uses is easy.
It's just a percentage. Now you know better. It's not a thermometer. It's more of an accounting ledger. Task manager samples cumulative execution time, computes deltas, normalizes them against total CPU consumed across the system, rounds the result, clamps off the ugly bits, and hands you a number that is fantastically useful. as long as you remember what question it's actually answering. And if you forget, well, then it can start to look misleading. Not because the code is wrong or dumb, but because reality is slippery and hard. If you found today's episode interesting or entertaining, remember I'm mostly in this for the subs and likes. So, I would be honored if you would consider leaving me one of each before you go today. And if you're already subscribed, thank you.
In the meantime, and in between time, I hope to see you next time right here in Dave's Garage.
Vidéos Similaires
She Lost Her Car... But We Still Helped Her!
RecoveryBoyz
129 views•2026-05-30
Deadly Got Talent Auditions You Should NEVER Try at Home!
gottalentglobal
5K views•2026-05-29
Cozy Cottage Jazz | Warm Morning Cafe Ambience 🌸
villagejazzhouse
846 views•2026-05-29
DeBoer Wants Alabama Tougher, Texas Tech Calls out the Texas Longhorns | TNR 5/29/26
NextRoundLive
2K views•2026-05-29
Smart Working Techniques for Faster and Safer Jobs Part 54✅ #construction #adamrose #workers
worksmart-98
2K views•2026-05-29
LIVE: Move Into Friday with Special Guest Ed O'Brien | Morning Becomes Eclectic
kcrw
778 views•2026-05-29
On Bended Knees - Jekalyn Carr (Official Live Worship)
halalafrika
7K views•2026-05-29
Black Hills To Badlands In A Nova Bought SIGHT UNSEEN-Going To Towns Tour with HUNDREDS of CLASSICS!
ViceGripGarage
52K views•2026-05-29











