diff --git a/.gitignore b/.gitignore index 3b557d2f..bf2c6dd1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ *.svg *.pdb *.user +*.launchSettings.json # New Visual Studio 2015 intellisense DB files # http://blogs.msdn.com/b/vcblog/archive/2015/11/11/new-improved-and-faster-database-engine.aspx *.VC.db @@ -41,6 +42,9 @@ etwpackage*.zip etwsymbols*.zip sourceindex.txt +# Avoid shipping nuget files and others in /obj/ directories. +obj/ + Debug/ Release/ *DoNotShip/ diff --git a/TraceProcessors/IdleWakeups/IdleWakeups.cs b/TraceProcessors/IdleWakeups/IdleWakeups.cs new file mode 100644 index 00000000..15242cbd --- /dev/null +++ b/TraceProcessors/IdleWakeups/IdleWakeups.cs @@ -0,0 +1,66 @@ +/* +Copyright 2021 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Detect idle wakeups in Chrome in an ETW using TraceProcessing +// Explanations of the techniques can be found here: +// https://randomascii.wordpress.com/2020/01/05/bulk-etw-trace-analysis-in-c/ + +// See this blog post for details of the Trace Processor package used to +// drive this: +// https://blogs.windows.com/windowsdeveloper/2019/05/09/announcing-traceprocessor-preview-0-1-0/ +// Note that this URL has changed once already, so caveat blog lector + +using Microsoft.Windows.EventTracing; +class IdleWakeups +{ + static void Main(string[] args) + { + foreach (string traceName in args) + { + Console.WriteLine("Processing trace '{0}'", traceName); + var settings = new TraceProcessorSettings + { + // Don't print a setup message on first run. + SuppressFirstTimeSetupMessage = true + }; + using (ITraceProcessor trace = TraceProcessor.Create(traceName, settings)) + { + // Specify what data we want, process the trace, then get the data. + var pendingContextSwitchData = trace.UseContextSwitchData(); + trace.Process(); + var csData = pendingContextSwitchData.Result; + + long chromeSwitches = 0; + long chromeIdleSwitches = 0; + // Iterate through all context switches in the trace. + foreach (var contextSwitch in csData.ContextSwitches) + { + var imageName = contextSwitch.SwitchIn.Process.ImageName; + var oldImageName = contextSwitch.SwitchOut.Process.ImageName; + if (imageName == "chrome.exe") + { + chromeSwitches++; + if (oldImageName == "Idle") + chromeIdleSwitches++; + } + } + Console.WriteLine("{0} idlewakeups out of {1} context switches ({2:P}).", + chromeIdleSwitches, chromeSwitches, + chromeIdleSwitches / (double)chromeSwitches); + } + } + } +} diff --git a/TraceProcessors/IdleWakeups/IdleWakeups.csproj b/TraceProcessors/IdleWakeups/IdleWakeups.csproj new file mode 100644 index 00000000..8eaa7cb3 --- /dev/null +++ b/TraceProcessors/IdleWakeups/IdleWakeups.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/TraceProcessors/IdleWakeups/IdleWakeups.sln b/TraceProcessors/IdleWakeups/IdleWakeups.sln new file mode 100644 index 00000000..a90b059f --- /dev/null +++ b/TraceProcessors/IdleWakeups/IdleWakeups.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdleWakeups", "IdleWakeups.csproj", "{B088F2D9-100B-401D-A43A-3358BF682195}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B088F2D9-100B-401D-A43A-3358BF682195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B088F2D9-100B-401D-A43A-3358BF682195}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B088F2D9-100B-401D-A43A-3358BF682195}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B088F2D9-100B-401D-A43A-3358BF682195}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1273C88D-6FDB-4224-9D13-03762DB203A5} + EndGlobalSection +EndGlobal diff --git a/TraceProcessors/TraceProcessors.sln b/TraceProcessors/TraceProcessors.sln index ba40437c..fe468668 100644 --- a/TraceProcessors/TraceProcessors.sln +++ b/TraceProcessors/TraceProcessors.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28803.202 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31919.166 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentifyChromeProcesses", "IdentifyChromeProcesses\IdentifyChromeProcesses.csproj", "{42AC0C9A-BBE7-4C8E-BB00-84D9C9FC8EE3}" EndProject @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeapSnapshotCompare", "Heap EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoConfCPUCounters", "VideoConfCPUCounters\VideoConfCPUCounters.csproj", "{C37B7893-D2B9-4DA1-835C-04339B38BFF7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdleWakeups", "IdleWakeups\IdleWakeups.csproj", "{3CD706EF-50E6-46EF-BF11-3AFB86C57E10}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -69,6 +71,18 @@ Global {C37B7893-D2B9-4DA1-835C-04339B38BFF7}.Release|x64.Build.0 = Release|Any CPU {C37B7893-D2B9-4DA1-835C-04339B38BFF7}.Release|x86.ActiveCfg = Release|Any CPU {C37B7893-D2B9-4DA1-835C-04339B38BFF7}.Release|x86.Build.0 = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|x64.ActiveCfg = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|x64.Build.0 = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|x86.ActiveCfg = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Debug|x86.Build.0 = Debug|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|Any CPU.Build.0 = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|x64.ActiveCfg = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|x64.Build.0 = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|x86.ActiveCfg = Release|Any CPU + {3CD706EF-50E6-46EF-BF11-3AFB86C57E10}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE