├── .gitignore
├── BottleneckCompileFinder
├── BottleneckCompileFinder.vcxproj
├── BottleneckCompileFinder.vcxproj.filters
├── main.cpp
└── packages.config
├── CODE_OF_CONDUCT.md
├── FunctionBottlenecks
├── FunctionBottlenecks.vcxproj
├── FunctionBottlenecks.vcxproj.filters
├── main.cpp
└── packages.config
├── LICENSE
├── LongCodeGenFinder
├── LongCodeGenFinder.vcxproj
├── LongCodeGenFinder.vcxproj.filters
├── main.cpp
└── packages.config
├── LongHeaderUnitFinder
├── LongHeaderUnitFinder.vcxproj
├── LongHeaderUnitFinder.vcxproj.filters
├── main.cpp
└── packages.config
├── LongModuleFinder
├── LongModuleFinder.vcxproj
├── LongModuleFinder.vcxproj.filters
├── main.cpp
└── packages.config
├── LongPrecompiledHeaderFinder
├── LongPrecompiledHeaderFinder.vcxproj
├── LongPrecompiledHeaderFinder.vcxproj.filters
├── main.cpp
└── packages.config
├── README.md
├── RecursiveTemplateInspector
├── RecursiveTemplateInspector.vcxproj
├── RecursiveTemplateInspector.vcxproj.filters
├── main.cpp
└── packages.config
├── SECURITY.md
├── Samples.sln
└── TopHeaders
├── TopHeaders.vcxproj
├── TopHeaders.vcxproj.filters
├── main.cpp
└── packages.config
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
352 | # vscode settings
353 | .vscode/
354 |
--------------------------------------------------------------------------------
/BottleneckCompileFinder/BottleneckCompileFinder.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}
24 | BottleneckCompileFinder
25 | 10.0
26 | BottleneckCompileFinder
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/BottleneckCompileFinder/BottleneckCompileFinder.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/BottleneckCompileFinder/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using namespace Microsoft::Cpp::BuildInsights;
7 | using namespace Activities;
8 | using namespace SimpleEvents;
9 |
10 | class BottleneckCompileFinder : public IAnalyzer
11 | {
12 | struct InvocationInfo
13 | {
14 | bool IsBottleneck;
15 | bool UsesParallelFlag;
16 | };
17 |
18 | public:
19 | BottleneckCompileFinder()
20 | {}
21 |
22 | AnalysisControl OnStartActivity(const EventStack& eventStack)
23 | override
24 | {
25 | MatchEventStackInMemberFunction(eventStack, this,
26 | &BottleneckCompileFinder::OnStartInvocation);
27 |
28 | return AnalysisControl::CONTINUE;
29 | }
30 |
31 | AnalysisControl OnStopActivity(const EventStack& eventStack)
32 | override
33 | {
34 | MatchEventStackInMemberFunction(eventStack, this,
35 | &BottleneckCompileFinder::OnStopInvocation);
36 |
37 | return AnalysisControl::CONTINUE;
38 | }
39 |
40 | AnalysisControl OnSimpleEvent(const EventStack& eventStack)
41 | override
42 | {
43 | MatchEventStackInMemberFunction(eventStack, this,
44 | &BottleneckCompileFinder::OnCompilerCommandLine);
45 |
46 | return AnalysisControl::CONTINUE;
47 | }
48 |
49 | void OnStartInvocation(InvocationGroup group)
50 | {
51 | // We need to match groups because CL can
52 | // start a linker, and a linker can restart
53 | // itself. When this happens, the event stack
54 | // contains the parent invocations in earlier
55 | // positions.
56 |
57 | // A linker that is spawned by a previous tool is
58 | // not considered an invocation that runs in
59 | // parallel with the tool that spawned it.
60 | if (group.Size() > 1) {
61 | return;
62 | }
63 |
64 | // An invocation is speculatively considered a bottleneck
65 | // if no other invocations are currently running when it starts.
66 | bool isBottleneck = concurrentInvocations_.empty();
67 |
68 | // If there is already an invocation running, it is no longer
69 | // considered a bottleneck because we are spawning another one
70 | // that will run alongside it. Clear its bottleneck flag.
71 | if (concurrentInvocations_.size() == 1) {
72 | concurrentInvocations_.begin()->second.IsBottleneck = false;
73 | }
74 |
75 | InvocationInfo& info = concurrentInvocations_[group.Back().EventInstanceId()];
76 |
77 | info.IsBottleneck = isBottleneck;
78 | }
79 |
80 | void OnCompilerCommandLine(Compiler cl, CommandLine commandLine)
81 | {
82 | auto it = concurrentInvocations_.find(cl.EventInstanceId());
83 |
84 | if (it == concurrentInvocations_.end()) {
85 | return;
86 | }
87 |
88 | // Keep track of CL invocations that don't use MP so that we can
89 | // warn the user if this invocation is a bottleneck.
90 |
91 | std::wstring str = commandLine.Value();
92 |
93 | if (str.find(L" /MP ") != std::wstring::npos ||
94 | str.find(L" -MP ") != std::wstring::npos)
95 | {
96 | it->second.UsesParallelFlag = true;
97 | }
98 | }
99 |
100 | void OnStopInvocation(Invocation invocation)
101 | {
102 | using namespace std::chrono;
103 |
104 | auto it = concurrentInvocations_.find(invocation.EventInstanceId());
105 |
106 | if (it == concurrentInvocations_.end()) {
107 | return;
108 | }
109 |
110 | if (invocation.Type() == Invocation::Type::CL &&
111 | it->second.IsBottleneck &&
112 | !it->second.UsesParallelFlag)
113 | {
114 | std::cout << std::endl << "WARNING: Found a compiler invocation that is a " <<
115 | "bottleneck but that doesn't use the /MP flag. Consider adding " <<
116 | "the /MP flag." << std::endl;
117 |
118 | std::cout << "Information about the invocation:" << std::endl;
119 | std::wcout << "Working directory: " << invocation.WorkingDirectory() << std::endl;
120 | std::cout << "Duration: " << duration_cast(invocation.Duration()).count() <<
121 | " s" << std::endl;
122 | }
123 |
124 | concurrentInvocations_.erase(invocation.EventInstanceId());
125 | }
126 |
127 | private:
128 | // A hash table that maps cl or link invocations to a flag
129 | // that indicates whether this invocation is a bottleneck.
130 | // In this sample, an invocation is considered a bottleneck
131 | // when no other compiler or linker is running alonside it
132 | // at any point.
133 | std::unordered_map concurrentInvocations_;
134 | };
135 |
136 | int main(int argc, char* argv[])
137 | {
138 | if (argc <= 1) return -1;
139 |
140 | BottleneckCompileFinder bcf;
141 |
142 | auto group = MakeStaticAnalyzerGroup(&bcf);
143 |
144 | // argv[1] should contain the path to a trace file
145 | int numberOfPasses = 1;
146 | return Analyze(argv[1], numberOfPasses, group);
147 | }
--------------------------------------------------------------------------------
/BottleneckCompileFinder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/FunctionBottlenecks/FunctionBottlenecks.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {F002C795-7D92-4146-8A7C-BBEB946F4309}
24 | FunctionBottlenecks
25 | 10.0
26 | FunctionBottlenecks
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/FunctionBottlenecks/FunctionBottlenecks.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/FunctionBottlenecks/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace Microsoft::Cpp::BuildInsights;
10 | using namespace Activities;
11 | using namespace SimpleEvents;
12 |
13 | class FunctionBottlenecks : public IAnalyzer
14 | {
15 | struct IdentifiedFunction
16 | {
17 | std::string Name;
18 | std::chrono::milliseconds Duration;
19 | double Percent;
20 | unsigned ForceInlineeSize;
21 |
22 | bool operator<(const IdentifiedFunction& other) const {
23 | return Duration > other.Duration;
24 | }
25 | };
26 |
27 | public:
28 | FunctionBottlenecks():
29 | pass_{0},
30 | cachedInvocationDurations_{},
31 | identifiedFunctions_{},
32 | forceInlineSizeCache_{}
33 | {}
34 |
35 | AnalysisControl OnBeginAnalysisPass() override
36 | {
37 | ++pass_;
38 | return AnalysisControl::CONTINUE;
39 | }
40 |
41 | AnalysisControl OnStopActivity(const EventStack& eventStack)
42 | override
43 | {
44 | switch (pass_)
45 | {
46 | case 1:
47 | MatchEventStackInMemberFunction(eventStack, this,
48 | &FunctionBottlenecks::OnStopInvocation);
49 | break;
50 |
51 | case 2:
52 | MatchEventStackInMemberFunction(eventStack, this,
53 | &FunctionBottlenecks::OnStopFunction);
54 | break;
55 |
56 | default:
57 | break;
58 | }
59 |
60 | return AnalysisControl::CONTINUE;
61 | }
62 |
63 | AnalysisControl OnSimpleEvent(const EventStack& eventStack)
64 | {
65 | if (pass_ > 1) {
66 | return AnalysisControl::CONTINUE;
67 | }
68 |
69 | MatchEventStackInMemberFunction(eventStack, this,
70 | &FunctionBottlenecks::ProcessForceInlinee);
71 |
72 | return AnalysisControl::CONTINUE;
73 | }
74 |
75 | void OnStopInvocation(Invocation invocation)
76 | {
77 | using namespace std::chrono;
78 |
79 | // Ignore very short invocations
80 | if (invocation.Duration() < std::chrono::seconds(1)) {
81 | return;
82 | }
83 |
84 | cachedInvocationDurations_[invocation.EventInstanceId()] =
85 | duration_cast(invocation.Duration());
86 | }
87 |
88 | void OnStopFunction(Invocation invocation, Function func)
89 | {
90 | using namespace std::chrono;
91 |
92 | auto itInvocation = cachedInvocationDurations_.find(
93 | invocation.EventInstanceId());
94 |
95 | if (itInvocation == cachedInvocationDurations_.end()) {
96 | return;
97 | }
98 |
99 | auto itForceInlineSize = forceInlineSizeCache_.find(
100 | func.EventInstanceId());
101 |
102 | unsigned forceInlineSize =
103 | itForceInlineSize == forceInlineSizeCache_.end() ?
104 | 0 : itForceInlineSize->second;
105 |
106 | milliseconds functionMilliseconds =
107 | duration_cast(func.Duration());
108 |
109 | double functionTime = static_cast(
110 | functionMilliseconds.count());
111 |
112 | double invocationTime = static_cast(
113 | itInvocation->second.count());
114 |
115 | double percent = functionTime / invocationTime;
116 |
117 | if (percent > 0.05 && func.Duration() >= seconds(1))
118 | {
119 | identifiedFunctions_[func.EventInstanceId()]=
120 | { func.Name(), functionMilliseconds, percent,
121 | forceInlineSize };
122 | }
123 | }
124 |
125 | void ProcessForceInlinee(Function func, ForceInlinee inlinee)
126 | {
127 | forceInlineSizeCache_[func.EventInstanceId()] +=
128 | inlinee.Size();
129 | }
130 |
131 | AnalysisControl OnEndAnalysis() override
132 | {
133 | std::vector sortedFunctions;
134 |
135 | for (auto& p : identifiedFunctions_) {
136 | sortedFunctions.push_back(p.second);
137 | }
138 |
139 | std::sort(sortedFunctions.begin(), sortedFunctions.end());
140 |
141 | for (auto& func : sortedFunctions)
142 | {
143 | bool forceInlineHeavy = func.ForceInlineeSize >= 10000;
144 |
145 | std::string forceInlineIndicator = forceInlineHeavy ?
146 | ", *" : "";
147 |
148 | int percent = static_cast(func.Percent * 100);
149 |
150 | std::string percentString = "(" +
151 | std::to_string(percent) + "%" +
152 | forceInlineIndicator + ")";
153 |
154 | std::cout << std::setw(9) << std::right <<
155 | func.Duration.count();
156 | std::cout << " ms ";
157 | std::cout << std::setw(9) << std::left <<
158 | percentString;
159 | std::cout << " " << func.Name << std::endl;
160 | }
161 |
162 | return AnalysisControl::CONTINUE;
163 | }
164 |
165 | private:
166 | unsigned pass_;
167 |
168 | std::unordered_map cachedInvocationDurations_;
170 |
171 | std::unordered_map identifiedFunctions_;
173 |
174 | std::unordered_map forceInlineSizeCache_;
176 | };
177 |
178 | int main(int argc, char* argv[])
179 | {
180 | if (argc <= 1) return -1;
181 |
182 | std::cout.imbue(std::locale(""));
183 |
184 | FunctionBottlenecks fb;
185 |
186 | auto group = MakeStaticAnalyzerGroup(&fb);
187 |
188 | // argv[1] should contain the path to a trace file
189 | int numberOfPasses = 2;
190 | return Analyze(argv[1], numberOfPasses, group);
191 | }
--------------------------------------------------------------------------------
/FunctionBottlenecks/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/LongCodeGenFinder/LongCodeGenFinder.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}
24 | LongCodeGenFinder
25 | 10.0
26 | LongCodeGenFinder
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/LongCodeGenFinder/LongCodeGenFinder.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LongCodeGenFinder/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using namespace Microsoft::Cpp::BuildInsights;
5 | using namespace Activities;
6 |
7 | class LongCodeGenFinder : public IAnalyzer
8 | {
9 | public:
10 | // Called by the analysis driver every time an activity stop event
11 | // is seen in the trace.
12 | AnalysisControl OnStopActivity(const EventStack& eventStack) override
13 | {
14 | // This will check whether the event stack matches
15 | // TopFunctionsFinder::CheckForTopFunction's signature.
16 | // If it does, it will forward the event to the function.
17 |
18 | MatchEventStackInMemberFunction(eventStack, this,
19 | &LongCodeGenFinder::CheckForLongFunctionCodeGen);
20 |
21 | // Tells the analysis driver to proceed to the next event
22 |
23 | return AnalysisControl::CONTINUE;
24 | }
25 |
26 | // This function is used to capture Function activity events that are
27 | // within a CodeGeneration activity, and to print a list of functions
28 | // that take more than 500 milliseconds to generate.
29 |
30 | void CheckForLongFunctionCodeGen(CodeGeneration cg, Function f)
31 | {
32 | using namespace std::chrono;
33 |
34 | if (f.Duration() < milliseconds(500)) {
35 | return;
36 | }
37 |
38 | std::cout << "Duration: " << duration_cast(
39 | f.Duration()).count();
40 |
41 | std::cout << "\t Function Name: " << f.Name() << std::endl;
42 | }
43 | };
44 |
45 | int main(int argc, char *argv[])
46 | {
47 | if (argc <= 1) return -1;
48 |
49 | LongCodeGenFinder lcgf;
50 |
51 | // Let's make a group of analyzers that will receive
52 | // events in the trace. We only have one; easy!
53 | auto group = MakeStaticAnalyzerGroup(&lcgf);
54 |
55 | // argv[1] should contain the path to a trace file
56 | int numberOfPasses = 1;
57 | return Analyze(argv[1], numberOfPasses, group);
58 | }
--------------------------------------------------------------------------------
/LongCodeGenFinder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/LongHeaderUnitFinder/LongHeaderUnitFinder.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {f16c04c7-7f1b-4d43-b9c3-156d27d0cd5b}
24 | LongHeaderUnitFinder
25 | 10.0
26 | LongHeaderUnitFinder
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/LongHeaderUnitFinder/LongHeaderUnitFinder.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LongHeaderUnitFinder/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace Microsoft::Cpp::BuildInsights;
10 | using namespace Activities;
11 | using namespace SimpleEvents;
12 |
13 | class LongHeaderUnitFinder : public IAnalyzer
14 | {
15 | struct FrontEndPassData
16 | {
17 | std::wstring Name;
18 | unsigned InvocationId;
19 | double Duration;
20 |
21 | bool operator<(const FrontEndPassData& other) const {
22 | return Duration > other.Duration;
23 | }
24 | };
25 |
26 | public:
27 | LongHeaderUnitFinder() :
28 | cachedFrontEndPassIds_{},
29 | FrontEndPassData_{}
30 | {}
31 |
32 | AnalysisControl OnBeginAnalysisPass() override
33 | {
34 | return AnalysisControl::CONTINUE;
35 | }
36 |
37 | AnalysisControl OnStopActivity(const EventStack& eventStack)
38 | override
39 | {
40 | MatchEventStackInMemberFunction(eventStack, this,
41 | &LongHeaderUnitFinder::OnStopFrontEndPass);
42 |
43 | return AnalysisControl::CONTINUE;
44 | }
45 |
46 | AnalysisControl OnSimpleEvent(const EventStack& eventStack) override
47 | {
48 | MatchEventStackInMemberFunction(eventStack, this,
49 | &LongHeaderUnitFinder::OnHeaderUnitEvent);
50 |
51 | return AnalysisControl::CONTINUE;
52 | }
53 |
54 | void OnStopFrontEndPass(Compiler cl, FrontEndPass frontEndPass)
55 | {
56 | // if the EventInstanceId of the current FrontEndPass has been saved
57 |
58 | auto itInvocation = cachedFrontEndPassIds_.find(
59 | frontEndPass.EventInstanceId());
60 |
61 | if (itInvocation == cachedFrontEndPassIds_.end()) {
62 | return;
63 | }
64 |
65 | using namespace std::chrono;
66 |
67 | if (frontEndPass.Duration() < std::chrono::seconds(1)) {
68 | return;
69 | }
70 |
71 | double duration = static_cast(duration_cast(frontEndPass.Duration()).count()) / 1000;
72 |
73 | std::wstring inputSourcePathWstr(frontEndPass.InputSourcePath());
74 |
75 | FrontEndPassData_[frontEndPass.EventInstanceId()] = { inputSourcePathWstr, cl.InvocationId(), duration };
76 | }
77 |
78 | void OnHeaderUnitEvent(FrontEndPass frontEndPass, HeaderUnit hu)
79 | {
80 | // Save the EventInstanceId of the current FrontEndPass
81 | cachedFrontEndPassIds_.insert(frontEndPass.EventInstanceId());
82 | }
83 |
84 | AnalysisControl OnEndAnalysis() override
85 | {
86 | std::vector sortedFrontEndPassData;
87 |
88 | for (auto& p : FrontEndPassData_) {
89 | sortedFrontEndPassData.push_back(p.second);
90 | }
91 |
92 | std::sort(sortedFrontEndPassData.begin(), sortedFrontEndPassData.end());
93 |
94 | for (auto& frontEndPassData : sortedFrontEndPassData)
95 | {
96 | std::cout << "File Name: ";
97 | std::wcout << frontEndPassData.Name;
98 | std::cout << "\t\tCL Invocation " << frontEndPassData.InvocationId << "\t\tDuration: " << frontEndPassData.Duration << " s " << std::endl;
99 | }
100 |
101 | return AnalysisControl::CONTINUE;
102 | }
103 |
104 | private:
105 | std::unordered_set cachedFrontEndPassIds_;
106 |
107 | std::unordered_map FrontEndPassData_;
109 | };
110 |
111 | int main(int argc, char* argv[])
112 | {
113 | if (argc <= 1) return -1;
114 |
115 | LongHeaderUnitFinder lhuf;
116 |
117 | auto group = MakeStaticAnalyzerGroup(&lhuf);
118 |
119 | // argv[1] should contain the path to a trace file
120 | int numberOfPasses = 1;
121 |
122 | return Analyze(argv[1], numberOfPasses, group);
123 | }
--------------------------------------------------------------------------------
/LongHeaderUnitFinder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/LongModuleFinder/LongModuleFinder.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {1149112d-c4e7-4cc7-b9c7-2aed3a159f8e}
24 | LongModuleFinder
25 | 10.0
26 | LongModuleFinder
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/LongModuleFinder/LongModuleFinder.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LongModuleFinder/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace Microsoft::Cpp::BuildInsights;
10 | using namespace Activities;
11 | using namespace SimpleEvents;
12 |
13 | class LongModuleFinder : public IAnalyzer
14 | {
15 | struct FrontEndPassData
16 | {
17 | std::wstring Name;
18 | unsigned InvocationId;
19 | double Duration;
20 |
21 | bool operator<(const FrontEndPassData& other) const {
22 | return Duration > other.Duration;
23 | }
24 | };
25 |
26 | public:
27 | LongModuleFinder() :
28 | cachedFrontEndPassIds_{},
29 | FrontEndPassData_{}
30 | {}
31 |
32 | AnalysisControl OnBeginAnalysisPass() override
33 | {
34 | return AnalysisControl::CONTINUE;
35 | }
36 |
37 | AnalysisControl OnStopActivity(const EventStack& eventStack)
38 | override
39 | {
40 | MatchEventStackInMemberFunction(eventStack, this,
41 | &LongModuleFinder::OnStopFrontEndPass);
42 |
43 | return AnalysisControl::CONTINUE;
44 | }
45 |
46 | AnalysisControl OnSimpleEvent(const EventStack& eventStack) override
47 | {
48 | MatchEventStackInMemberFunction(eventStack, this,
49 | &LongModuleFinder::OnModuleEvent);
50 |
51 | return AnalysisControl::CONTINUE;
52 | }
53 |
54 | void OnStopFrontEndPass(Compiler cl, FrontEndPass frontEndPass)
55 | {
56 | // if the EventInstanceId of the current FrontEndPass has been saved
57 |
58 | auto itInvocation = cachedFrontEndPassIds_.find(
59 | frontEndPass.EventInstanceId());
60 |
61 | if (itInvocation == cachedFrontEndPassIds_.end()) {
62 | return;
63 | }
64 |
65 | using namespace std::chrono;
66 |
67 | if (frontEndPass.Duration() < std::chrono::seconds(1)) {
68 | return;
69 | }
70 |
71 | double duration = static_cast(duration_cast(frontEndPass.Duration()).count()) / 1000;
72 |
73 | std::wstring inputSourcePathWstr(frontEndPass.InputSourcePath());
74 |
75 | FrontEndPassData_[frontEndPass.EventInstanceId()] = { inputSourcePathWstr, cl.InvocationId(), duration };
76 | }
77 |
78 | void OnModuleEvent(FrontEndPass frontEndPass, Module m)
79 | {
80 | // Save the EventInstanceId of the current FrontEndPass
81 | cachedFrontEndPassIds_.insert(frontEndPass.EventInstanceId());
82 | }
83 |
84 | AnalysisControl OnEndAnalysis() override
85 | {
86 | std::vector sortedFrontEndPassData;
87 |
88 | for (auto& p : FrontEndPassData_) {
89 | sortedFrontEndPassData.push_back(p.second);
90 | }
91 |
92 | std::sort(sortedFrontEndPassData.begin(), sortedFrontEndPassData.end());
93 |
94 | for (auto& frontEndPassData : sortedFrontEndPassData)
95 | {
96 | std::cout << "File Name: ";
97 | std::wcout << frontEndPassData.Name;
98 | std::cout << "\t\tCL Invocation " << frontEndPassData.InvocationId << "\t\tDuration: " << frontEndPassData.Duration << " s " << std::endl;
99 | }
100 |
101 | return AnalysisControl::CONTINUE;
102 | }
103 |
104 | private:
105 | std::unordered_set cachedFrontEndPassIds_;
106 |
107 | std::unordered_map FrontEndPassData_;
109 | };
110 |
111 | int main(int argc, char* argv[])
112 | {
113 | if (argc <= 1) return -1;
114 |
115 | LongModuleFinder lmf;
116 |
117 | auto group = MakeStaticAnalyzerGroup(&lmf);
118 |
119 | // argv[1] should contain the path to a trace file
120 | int numberOfPasses = 1;
121 |
122 | return Analyze(argv[1], numberOfPasses, group);
123 | }
--------------------------------------------------------------------------------
/LongModuleFinder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/LongPrecompiledHeaderFinder/LongPrecompiledHeaderFinder.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {691b8829-ae90-4e85-b809-45d714f66cc0}
24 | LongPrecompiledHeaderFinder
25 | 10.0
26 | LongPrecompiledHeaderFinder
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
76 |
77 |
78 | true
79 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
80 |
81 |
82 | false
83 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
84 |
85 |
86 | false
87 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
88 |
89 |
90 |
91 | Level3
92 | true
93 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
94 | true
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 | true
133 | true
134 | true
135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 |
138 |
139 | Console
140 | true
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/LongPrecompiledHeaderFinder/LongPrecompiledHeaderFinder.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LongPrecompiledHeaderFinder/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace Microsoft::Cpp::BuildInsights;
10 | using namespace Activities;
11 | using namespace SimpleEvents;
12 |
13 | class LongPrecompiledHeaderFinder : public IAnalyzer
14 | {
15 | struct FrontEndPassData
16 | {
17 | std::wstring Name;
18 | unsigned InvocationId;
19 | double Duration;
20 |
21 | bool operator<(const FrontEndPassData& other) const {
22 | return Duration > other.Duration;
23 | }
24 | };
25 |
26 | public:
27 | LongPrecompiledHeaderFinder() :
28 | cachedFrontEndPassIds_{},
29 | FrontEndPassData_{}
30 | {}
31 |
32 | AnalysisControl OnBeginAnalysisPass() override
33 | {
34 | return AnalysisControl::CONTINUE;
35 | }
36 |
37 | AnalysisControl OnStopActivity(const EventStack& eventStack)
38 | override
39 | {
40 | MatchEventStackInMemberFunction(eventStack, this,
41 | &LongPrecompiledHeaderFinder::OnStopFrontEndPass);
42 |
43 | return AnalysisControl::CONTINUE;
44 | }
45 |
46 | AnalysisControl OnSimpleEvent(const EventStack& eventStack) override
47 | {
48 | MatchEventStackInMemberFunction(eventStack, this,
49 | &LongPrecompiledHeaderFinder::OnPrecompiledHeaderEvent);
50 |
51 | return AnalysisControl::CONTINUE;
52 | }
53 |
54 | void OnStopFrontEndPass(Compiler cl, FrontEndPass frontEndPass)
55 | {
56 | // if the EventInstanceId of the current FrontEndPass has been saved
57 |
58 | auto itInvocation = cachedFrontEndPassIds_.find(
59 | frontEndPass.EventInstanceId());
60 |
61 | if (itInvocation == cachedFrontEndPassIds_.end()) {
62 | return;
63 | }
64 |
65 | using namespace std::chrono;
66 |
67 | if (frontEndPass.Duration() < std::chrono::seconds(1)) {
68 | return;
69 | }
70 |
71 | double duration = static_cast(duration_cast(frontEndPass.Duration()).count()) / 1000;
72 |
73 | std::wstring inputSourcePathWstr(frontEndPass.InputSourcePath());
74 |
75 | FrontEndPassData_[frontEndPass.EventInstanceId()] = { inputSourcePathWstr, cl.InvocationId(), duration };
76 | }
77 |
78 | void OnPrecompiledHeaderEvent(FrontEndPass frontEndPass, PrecompiledHeader pch)
79 | {
80 | // Save the EventInstanceId of the current FrontEndPass
81 | cachedFrontEndPassIds_.insert(frontEndPass.EventInstanceId());
82 | }
83 |
84 | AnalysisControl OnEndAnalysis() override
85 | {
86 | std::vector sortedFrontEndPassData;
87 |
88 | for (auto& p : FrontEndPassData_) {
89 | sortedFrontEndPassData.push_back(p.second);
90 | }
91 |
92 | std::sort(sortedFrontEndPassData.begin(), sortedFrontEndPassData.end());
93 |
94 | for (auto& frontEndPassData : sortedFrontEndPassData)
95 | {
96 | std::cout << "File Name: ";
97 | std::wcout << frontEndPassData.Name;
98 | std::cout << "\t\tCL Invocation " << frontEndPassData.InvocationId << "\t\tDuration: " << frontEndPassData.Duration << " s " << std::endl;
99 | }
100 |
101 | return AnalysisControl::CONTINUE;
102 | }
103 |
104 | private:
105 | std::unordered_set cachedFrontEndPassIds_;
106 |
107 | std::unordered_map FrontEndPassData_;
109 | };
110 |
111 | int main(int argc, char* argv[])
112 | {
113 | if (argc <= 1) return -1;
114 |
115 | LongPrecompiledHeaderFinder lpchf;
116 |
117 | auto group = MakeStaticAnalyzerGroup(&lpchf);
118 |
119 | // argv[1] should contain the path to a trace file
120 | int numberOfPasses = 1;
121 |
122 | return Analyze(argv[1], numberOfPasses, group);
123 | }
--------------------------------------------------------------------------------
/LongPrecompiledHeaderFinder/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | languages:
4 | - C++
5 | products:
6 | - cpp-build-insights
7 | description: "This repository provides buildable and runnable samples for the C++ Build Insights SDK. Use it as a learning resource."
8 | urlFragment: "cpp-build-insights-samples"
9 | ---
10 |
11 | # C++ Build Insights SDK samples
12 |
13 | 
14 |
15 | This repository provides buildable and runnable samples for the C++ Build Insights SDK. Use it as a learning resource.
16 |
17 | ## Contents
18 |
19 | | Sample | Description |
20 | |-------------------|--------------------------------------------|
21 | | BottleneckCompileFinder | Finds CL invocations that are bottlenecks and don't use /MP. |
22 | | FunctionBottlenecks | Prints a list of functions that are code generation bottlenecks within their CL or Link invocation. |
23 | | LongCodeGenFinder | Lists the functions that take more than 500 milliseconds to generate in your entire build. |
24 | | RecursiveTemplateInspector | Identifies costly recursive template instantiations. |
25 | | TopHeaders | Determines which headers you might want to precompile. |
26 | | LongModuleFinder | Identifies costly module interface IFC creation. Requires trace with code built using MSVC version 16.10 or later and using SDK version Microsoft.Cpp.BuildInsights 1.2.0 or later. |
27 | | LongHeaderUnitFinder | Identifies costly header unit IFC creation. Requires trace with code built using MSVC version 16.10 or later and using SDK version Microsoft.Cpp.BuildInsights 1.2.0 or later. |
28 | | LongPrecompiledHeaderFinder | Identifies costly precompiled header (PCH) IFC creation. Requires trace with code built using MSVC version 16.10 or later and using SDK version Microsoft.Cpp.BuildInsights 1.2.0 or later. |
29 |
30 | ## Prerequisites
31 |
32 | In order to build and run the samples in this repository, you need:
33 |
34 | - Visual Studio 2017 and above.
35 | - Windows 8 and above.
36 |
37 | ## Build steps
38 |
39 | 1. Clone the repository on your machine.
40 | 1. Open the Visual Studio solution file. Each sample is a separate project within the solution.
41 | 1. All samples rely on the C++ Build Insights SDK NuGet package. Restore NuGet packages and accept the license for the SDK.
42 | 1. Build the desired configuration for the samples that interest you. Available platforms are x86 and x64, and available configurations are *Debug* and *Release*.
43 | 1. Samples will be built in their own directory following this formula: `{RepositoryRoot}\out\{SampleName}`.
44 |
45 | ## Running the samples
46 |
47 | 1. The samples require *CppBuildInsights.dll* and *KernelTraceControl.dll* to run. These files are available in the C++ Build Insights NuGet package. When building samples, these files are automatically copied next to them in their respective output directory. If you are going to move a sample around on your machine, please be sure to move these DLL's along with it.
48 | 1. Collect a trace of the build you want to analyze with the sample. You can do this using two methods:
49 | 1. Use vcperf:
50 | 1. Open an elevated x64 Native Tools Command Prompt for VS 2019.
51 | 1. Run the following command: `vcperf /start MySessionName`
52 | 1. Build your project. You do not need to use the same command prompt for building.
53 | 1. Run the following command: `vcperf /stopnoanalyze MySessionName outputTraceFile.etl`
54 | 1. Programmatically: see the [C++ Build Insights SDK](https://docs.microsoft.com/cpp/build-insights/reference/sdk/overview?view=vs-2019) documentation for details.
55 | 1. Invoke the sample, passing your trace as the first parameter.
56 |
57 | ## Contributing
58 |
59 | This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com).
60 |
61 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
62 |
63 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
64 |
--------------------------------------------------------------------------------
/RecursiveTemplateInspector/RecursiveTemplateInspector.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}
24 | RecursiveTemplateInspector
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v142
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v142
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v142
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v142
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | false
74 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
75 |
76 |
77 | true
78 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
79 |
80 |
81 | true
82 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
83 |
84 |
85 | false
86 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
87 |
88 |
89 |
90 | Level3
91 | true
92 | true
93 | true
94 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
95 | true
96 |
97 |
98 | Console
99 | true
100 | true
101 | true
102 |
103 |
104 |
105 |
106 | Level3
107 | true
108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
109 | true
110 |
111 |
112 | Console
113 | true
114 |
115 |
116 |
117 |
118 | Level3
119 | true
120 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 |
127 |
128 |
129 |
130 | Level3
131 | true
132 | true
133 | true
134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
135 | true
136 |
137 |
138 | Console
139 | true
140 | true
141 | true
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/RecursiveTemplateInspector/RecursiveTemplateInspector.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RecursiveTemplateInspector/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | using namespace Microsoft::Cpp::BuildInsights;
11 | using namespace Activities;
12 | using namespace SimpleEvents;
13 |
14 | class RecursiveTemplateInspector : public IAnalyzer
15 | {
16 | struct TemplateSpecializationInfo
17 | {
18 | std::chrono::nanoseconds TotalInstantiationTime;
19 | size_t InstantiationCount;
20 | size_t MaxDepth;
21 | std::string RootSpecializationName;
22 | std::wstring File;
23 |
24 | std::unordered_set VisitedInstantiations;
25 |
26 | bool operator<(const TemplateSpecializationInfo& other) const {
27 | return TotalInstantiationTime > other.TotalInstantiationTime;
28 | }
29 | };
30 |
31 | public:
32 | RecursiveTemplateInspector(int specializationCountToDump):
33 | specializationCountToDump_{
34 | specializationCountToDump > 0 ? specializationCountToDump : 5 }
35 | {
36 | }
37 |
38 | AnalysisControl OnStopActivity(const EventStack& eventStack)
39 | override
40 | {
41 | MatchEventStackInMemberFunction(eventStack, this,
42 | &RecursiveTemplateInspector::OnTemplateRecursionTreeBranch);
43 |
44 | return AnalysisControl::CONTINUE;
45 | }
46 |
47 | AnalysisControl OnSimpleEvent(const EventStack& eventStack)
48 | override
49 | {
50 | MatchEventStackInMemberFunction(eventStack, this,
51 | &RecursiveTemplateInspector::OnSymbolName);
52 |
53 | return AnalysisControl::CONTINUE;
54 | }
55 |
56 | void OnTemplateRecursionTreeBranch(FrontEndPass fe,
57 | TemplateInstantiationGroup recursionTreeBranch)
58 | {
59 | const TemplateInstantiation& root = recursionTreeBranch[0];
60 | const TemplateInstantiation& current = recursionTreeBranch.Back();
61 |
62 | auto& info = rootSpecializations_[root.SpecializationSymbolKey()];
63 |
64 | auto& visitedSet = info.VisitedInstantiations;
65 |
66 | if (visitedSet.find(current.EventInstanceId()) == visitedSet.end())
67 | {
68 | // We have a new unvisited branch. Update the max depth of the
69 | // recursion tree.
70 |
71 | info.MaxDepth = std::max(info.MaxDepth, recursionTreeBranch.Size());
72 |
73 | for (size_t idx = recursionTreeBranch.Size(); idx-- > 0;)
74 | {
75 | const TemplateInstantiation& ti = recursionTreeBranch[idx];
76 |
77 | auto p = visitedSet.insert(ti.EventInstanceId());
78 |
79 | bool wasVisited = !p.second;
80 |
81 | if (wasVisited)
82 | {
83 | // Stop once we reach a visited template instantiation,
84 | // because its parents will also have been visited.
85 | break;
86 | }
87 |
88 | ++info.InstantiationCount;
89 | }
90 | }
91 |
92 | if (recursionTreeBranch.Size() != 1) {
93 | return;
94 | }
95 |
96 | // The end of a hierarchy's instantiation corresponds to the stop
97 | // event of the root specialization's instantiation. When we reach
98 | // that point, we update the total instantiation time of the hierarchy.
99 |
100 | info.TotalInstantiationTime = root.Duration();
101 |
102 | info.File = fe.InputSourcePath() ? fe.InputSourcePath() :
103 | fe.OutputObjectPath();
104 |
105 | visitedSet.clear();
106 | }
107 |
108 | void OnSymbolName(SymbolName symbolName)
109 | {
110 | auto it = rootSpecializations_.find(symbolName.Key());
111 |
112 | if (it == rootSpecializations_.end()) {
113 | return;
114 | }
115 |
116 | it->second.RootSpecializationName = symbolName.Name();
117 | }
118 |
119 | AnalysisControl OnEndAnalysis() override
120 | {
121 | using namespace std::chrono;
122 |
123 | auto topSpecializations = GetTopInstantiations();
124 |
125 | if (specializationCountToDump_ == 1) {
126 | std::cout << "Top template instantiation hierarchy:";
127 | }
128 | else {
129 | std::cout << "Top " << specializationCountToDump_ <<
130 | " template instantiation " << "hierarchies";
131 | }
132 |
133 | std::cout << std::endl << std::endl;
134 |
135 | for (auto& info : topSpecializations)
136 | {
137 | std::wcout << "File: " <<
138 | info.File << std::endl;
139 | std::cout << "Duration: " <<
140 | duration_cast(
141 | info.TotalInstantiationTime).count() <<
142 | " ms" << std::endl;
143 | std::cout << "Max Depth: " <<
144 | info.MaxDepth << std::endl;
145 | std::cout << "Instantiations: " <<
146 | info.InstantiationCount << std::endl;
147 | std::cout << "Root Name: " <<
148 | info.RootSpecializationName << std::endl << std::endl;
149 | }
150 |
151 | return AnalysisControl::CONTINUE;
152 | }
153 |
154 | private:
155 | std::multiset GetTopInstantiations()
156 | {
157 | std::multiset topSpecializations;
158 |
159 | for (auto& p : rootSpecializations_)
160 | {
161 | if (topSpecializations.size() < specializationCountToDump_) {
162 | topSpecializations.insert(p.second);
163 | }
164 | else
165 | {
166 | auto itLast = --topSpecializations.end();
167 |
168 | if (p.second.TotalInstantiationTime >=
169 | itLast->TotalInstantiationTime)
170 | {
171 | topSpecializations.erase(itLast);
172 | topSpecializations.insert(p.second);
173 | }
174 | }
175 | }
176 |
177 | return topSpecializations;
178 | }
179 |
180 | // A hash table that stores information about template instantiations
181 | // that are at the root of a recursive instantiation hierarchy.
182 | std::unordered_map rootSpecializations_;
183 |
184 | int specializationCountToDump_;
185 | };
186 |
187 | int main(int argc, char* argv[])
188 | {
189 | if (argc <= 1) return -1;
190 |
191 | int specializationCountToDump = 0;
192 |
193 | if (argc >= 3) {
194 | specializationCountToDump = std::atoi(argv[2]);
195 | }
196 |
197 | RecursiveTemplateInspector rti{specializationCountToDump};
198 |
199 | auto group = MakeStaticAnalyzerGroup(&rti);
200 |
201 | // argv[1] should contain the path to a trace file
202 | int numberOfPasses = 1;
203 | return Analyze(argv[1], numberOfPasses, group);
204 | }
--------------------------------------------------------------------------------
/RecursiveTemplateInspector/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Samples.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29806.167
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LongCodeGenFinder", "LongCodeGenFinder\LongCodeGenFinder.vcxproj", "{0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BottleneckCompileFinder", "BottleneckCompileFinder\BottleneckCompileFinder.vcxproj", "{771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RecursiveTemplateInspector", "RecursiveTemplateInspector\RecursiveTemplateInspector.vcxproj", "{2F8A1B93-522E-449E-A7E2-2AFC0910DF48}"
11 | EndProject
12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TopHeaders", "TopHeaders\TopHeaders.vcxproj", "{A99D36F8-E953-4C59-AD45-93597900CAFF}"
13 | EndProject
14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunctionBottlenecks", "FunctionBottlenecks\FunctionBottlenecks.vcxproj", "{F002C795-7D92-4146-8A7C-BBEB946F4309}"
15 | EndProject
16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LongModuleFinder", "LongModuleFinder\LongModuleFinder.vcxproj", "{1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}"
17 | EndProject
18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LongPrecompiledHeaderFinder", "LongPrecompiledHeaderFinder\LongPrecompiledHeaderFinder.vcxproj", "{691B8829-AE90-4E85-B809-45D714F66CC0}"
19 | EndProject
20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LongHeaderUnitFinder", "LongHeaderUnitFinder\LongHeaderUnitFinder.vcxproj", "{F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|x64 = Debug|x64
25 | Debug|x86 = Debug|x86
26 | Release|x64 = Release|x64
27 | Release|x86 = Release|x86
28 | EndGlobalSection
29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
30 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Debug|x64.ActiveCfg = Debug|x64
31 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Debug|x64.Build.0 = Debug|x64
32 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Debug|x86.ActiveCfg = Debug|Win32
33 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Debug|x86.Build.0 = Debug|Win32
34 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Release|x64.ActiveCfg = Release|x64
35 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Release|x64.Build.0 = Release|x64
36 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Release|x86.ActiveCfg = Release|Win32
37 | {0C9761DD-6792-4F43-8DEF-C0D697DDDFA1}.Release|x86.Build.0 = Release|Win32
38 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Debug|x64.ActiveCfg = Debug|x64
39 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Debug|x64.Build.0 = Debug|x64
40 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Debug|x86.ActiveCfg = Debug|Win32
41 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Debug|x86.Build.0 = Debug|Win32
42 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Release|x64.ActiveCfg = Release|x64
43 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Release|x64.Build.0 = Release|x64
44 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Release|x86.ActiveCfg = Release|Win32
45 | {771D60A2-EDC9-4CA1-BA93-F2B53CBC357D}.Release|x86.Build.0 = Release|Win32
46 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Debug|x64.ActiveCfg = Debug|x64
47 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Debug|x64.Build.0 = Debug|x64
48 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Debug|x86.ActiveCfg = Debug|Win32
49 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Debug|x86.Build.0 = Debug|Win32
50 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Release|x64.ActiveCfg = Release|x64
51 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Release|x64.Build.0 = Release|x64
52 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Release|x86.ActiveCfg = Release|Win32
53 | {2F8A1B93-522E-449E-A7E2-2AFC0910DF48}.Release|x86.Build.0 = Release|Win32
54 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Debug|x64.ActiveCfg = Debug|x64
55 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Debug|x64.Build.0 = Debug|x64
56 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Debug|x86.ActiveCfg = Debug|Win32
57 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Debug|x86.Build.0 = Debug|Win32
58 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Release|x64.ActiveCfg = Release|x64
59 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Release|x64.Build.0 = Release|x64
60 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Release|x86.ActiveCfg = Release|Win32
61 | {A99D36F8-E953-4C59-AD45-93597900CAFF}.Release|x86.Build.0 = Release|Win32
62 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Debug|x64.ActiveCfg = Debug|x64
63 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Debug|x64.Build.0 = Debug|x64
64 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Debug|x86.ActiveCfg = Debug|Win32
65 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Debug|x86.Build.0 = Debug|Win32
66 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Release|x64.ActiveCfg = Release|x64
67 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Release|x64.Build.0 = Release|x64
68 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Release|x86.ActiveCfg = Release|Win32
69 | {F002C795-7D92-4146-8A7C-BBEB946F4309}.Release|x86.Build.0 = Release|Win32
70 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Debug|x64.ActiveCfg = Debug|x64
71 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Debug|x64.Build.0 = Debug|x64
72 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Debug|x86.ActiveCfg = Debug|Win32
73 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Debug|x86.Build.0 = Debug|Win32
74 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Release|x64.ActiveCfg = Release|x64
75 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Release|x64.Build.0 = Release|x64
76 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Release|x86.ActiveCfg = Release|Win32
77 | {1149112D-C4E7-4CC7-B9C7-2AED3A159F8E}.Release|x86.Build.0 = Release|Win32
78 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Debug|x64.ActiveCfg = Debug|x64
79 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Debug|x64.Build.0 = Debug|x64
80 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Debug|x86.ActiveCfg = Debug|Win32
81 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Debug|x86.Build.0 = Debug|Win32
82 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Release|x64.ActiveCfg = Release|x64
83 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Release|x64.Build.0 = Release|x64
84 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Release|x86.ActiveCfg = Release|Win32
85 | {691B8829-AE90-4E85-B809-45D714F66CC0}.Release|x86.Build.0 = Release|Win32
86 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Debug|x64.ActiveCfg = Debug|x64
87 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Debug|x64.Build.0 = Debug|x64
88 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Debug|x86.ActiveCfg = Debug|Win32
89 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Debug|x86.Build.0 = Debug|Win32
90 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Release|x64.ActiveCfg = Release|x64
91 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Release|x64.Build.0 = Release|x64
92 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Release|x86.ActiveCfg = Release|Win32
93 | {F16C04C7-7F1B-4D43-B9C3-156D27D0CD5B}.Release|x86.Build.0 = Release|Win32
94 | EndGlobalSection
95 | GlobalSection(SolutionProperties) = preSolution
96 | HideSolutionNode = FALSE
97 | EndGlobalSection
98 | GlobalSection(ExtensibilityGlobals) = postSolution
99 | SolutionGuid = {24E22F67-89F7-404A-99B5-BBD9D945B0CD}
100 | EndGlobalSection
101 | EndGlobal
102 |
--------------------------------------------------------------------------------
/TopHeaders/TopHeaders.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | {A99D36F8-E953-4C59-AD45-93597900CAFF}
24 | TopHeaders
25 | 10.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v142
32 | Unicode
33 |
34 |
35 | Application
36 | false
37 | v142
38 | true
39 | Unicode
40 |
41 |
42 | Application
43 | true
44 | v142
45 | Unicode
46 |
47 |
48 | Application
49 | false
50 | v142
51 | true
52 | Unicode
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | false
74 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
75 |
76 |
77 | true
78 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
79 |
80 |
81 | true
82 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
83 |
84 |
85 | false
86 | $(SolutionDir)out\$(Platform)\$(Configuration)\$(ProjectName)\
87 |
88 |
89 |
90 | Level3
91 | true
92 | true
93 | true
94 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
95 | true
96 |
97 |
98 | Console
99 | true
100 | true
101 | true
102 |
103 |
104 |
105 |
106 | Level3
107 | true
108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
109 | true
110 |
111 |
112 | Console
113 | true
114 |
115 |
116 |
117 |
118 | Level3
119 | true
120 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 |
127 |
128 |
129 |
130 | Level3
131 | true
132 | true
133 | true
134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
135 | true
136 |
137 |
138 | Console
139 | true
140 | true
141 | true
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/TopHeaders/TopHeaders.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TopHeaders/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | using namespace Microsoft::Cpp::BuildInsights;
12 | using namespace Activities;
13 |
14 | class TopHeaders : public IAnalyzer
15 | {
16 | struct FileInfo
17 | {
18 | std::chrono::nanoseconds TotalParsingTime;
19 | std::string Path;
20 | std::unordered_set PassIds;
21 |
22 | bool operator<(const FileInfo& other) const {
23 | return TotalParsingTime > other.TotalParsingTime;
24 | }
25 | };
26 |
27 | public:
28 | TopHeaders(int headerCountToDump):
29 | headerCountToDump_{headerCountToDump > 0 ?
30 | headerCountToDump : 5},
31 | frontEndAggregatedDuration_{0},
32 | fileInfo_{}
33 | {}
34 |
35 | AnalysisControl OnStopActivity(const EventStack& eventStack) override
36 | {
37 | switch (eventStack.Back().EventId())
38 | {
39 | case EVENT_ID_FRONT_END_FILE:
40 | MatchEventStackInMemberFunction(eventStack, this,
41 | &TopHeaders::OnStopFile);
42 | break;
43 |
44 | case EVENT_ID_FRONT_END_PASS:
45 | // Keep track of the overall front-end aggregated duration.
46 | // We use this value when determining how significant is
47 | // a header's total parsing time when compared to the total
48 | // front-end time.
49 | frontEndAggregatedDuration_ += eventStack.Back().Duration();
50 | break;
51 |
52 | default:
53 | break;
54 | }
55 |
56 | return AnalysisControl::CONTINUE;
57 | }
58 |
59 | AnalysisControl OnStopFile(FrontEndPass fe, FrontEndFile file)
60 | {
61 | // Make the path lowercase for comparing
62 | std::string path = file.Path();
63 |
64 | std::transform(path.begin(), path.end(), path.begin(),
65 | [](unsigned char c) { return std::tolower(c); });
66 |
67 | auto result = fileInfo_.try_emplace(std::move(path), FileInfo{});
68 |
69 | auto it = result.first;
70 | bool wasInserted = result.second;
71 |
72 | FileInfo& fi = it->second;
73 |
74 | fi.PassIds.insert(fe.EventInstanceId());
75 | fi.TotalParsingTime += file.Duration();
76 |
77 | if (result.second) {
78 | fi.Path = file.Path();
79 | }
80 |
81 | return AnalysisControl::CONTINUE;
82 | }
83 |
84 | AnalysisControl OnEndAnalysis() override
85 | {
86 | using namespace std::chrono;
87 |
88 | auto topHeaders = GetTopHeaders();
89 |
90 | if (headerCountToDump_ == 1) {
91 | std::cout << "Top header file:";
92 | }
93 | else {
94 | std::cout << "Top " << headerCountToDump_ <<
95 | " header files:";
96 | }
97 |
98 | std::cout << std::endl << std::endl;
99 |
100 | for (auto& info : topHeaders)
101 | {
102 | double frontEndPercentage =
103 | static_cast(info.TotalParsingTime.count()) /
104 | frontEndAggregatedDuration_.count() * 100.;
105 |
106 | std::cout << "Aggregated Parsing Duration: " <<
107 | duration_cast(
108 | info.TotalParsingTime).count() <<
109 | " ms" << std::endl;
110 | std::cout << "Front-End Time Percentage: " <<
111 | std::setprecision(2) << frontEndPercentage << "% " <<
112 | std::endl;
113 | std::cout << "Inclusion Count: " <<
114 | info.PassIds.size() << std::endl;
115 | std::cout << "Path: " <<
116 | info.Path << std::endl << std::endl;
117 | }
118 |
119 | return AnalysisControl::CONTINUE;
120 | }
121 |
122 | private:
123 | std::multiset GetTopHeaders()
124 | {
125 | std::multiset topHeaders;
126 |
127 | for (auto& p : fileInfo_)
128 | {
129 | if (topHeaders.size() < headerCountToDump_) {
130 | topHeaders.insert(p.second);
131 | }
132 | else
133 | {
134 | auto itLast = --topHeaders.end();
135 |
136 | if (p.second.TotalParsingTime >
137 | itLast->TotalParsingTime)
138 | {
139 | topHeaders.insert(p.second);
140 | topHeaders.erase(itLast);
141 | }
142 | }
143 | }
144 |
145 | return topHeaders;
146 | }
147 |
148 | int headerCountToDump_;
149 |
150 | std::chrono::nanoseconds frontEndAggregatedDuration_;
151 |
152 | std::unordered_map fileInfo_;
153 | };
154 |
155 | int main(int argc, char* argv[])
156 | {
157 | if (argc <= 1) return -1;
158 |
159 | int headerCountToDump = 0;
160 |
161 | if (argc >= 3) {
162 | headerCountToDump = std::atoi(argv[2]);
163 | }
164 |
165 | TopHeaders th{ headerCountToDump };
166 |
167 | auto group = MakeStaticAnalyzerGroup(&th);
168 |
169 | // argv[1] should contain the path to a trace file
170 | int numberOfPasses = 1;
171 | return Analyze(argv[1], numberOfPasses, group);
172 | }
--------------------------------------------------------------------------------
/TopHeaders/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------