{"id":15741,"date":"2011-01-31T00:01:00","date_gmt":"2011-01-31T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/01\/31\/use-powershell-to-simplify-collecting-performance-information\/"},"modified":"2011-01-31T00:01:00","modified_gmt":"2011-01-31T00:01:00","slug":"use-powershell-to-simplify-collecting-performance-information","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-simplify-collecting-performance-information\/","title":{"rendered":"Use PowerShell to Simplify Collecting Performance Information"},"content":{"rendered":"<p>&nbsp;<b>Summary<\/b>: Learn how to use Windows PowerShell to simplify collecting performance information from your servers.<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" \/><\/p>\n<p>Hey, Scripting Guy! We are having performance problems with several of our servers. It is really strange, because if you were to look at the specifications, you would think they are awesome boxes. What I need to do is to collect performance counter information on these things, but I would like to be able to use a script because there are several boxes that need to be analyzed. I really need to find the performance bottleneck, because I do not think the servers are underpowered; I think there is something amiss instead. The thing is that my boss wants to add memory because he says, &ldquo;With Windows you always need more RAM.&rdquo; However, if he buys a bunch of expensive RAM and it does not solve the problem, he will blame me. Help, the situation is getting serious. <\/p>\n<p>&mdash;AC<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" \/> Hello AC, <\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, here. Back when I was in consulting I used to do a lot of performance testing on servers, and I thought it was a lot of fun. What is cool is when you find evidence of a particular problem and you solve a serious issue. One thing I found out is that people really want to see the evidence before they will make changes&mdash;especially changes that cost money. Therefore, in your case, your boss is a little strange in this regard. Oh well. In the past, the solution for automating performance counters was to use the WMI classes. With Windows PowerShell 2.0, the WMI classes are not required, because there are some excellent cmdlets. <\/p>\n<p>One of the problems with automating performance counters is knowing which counter to add. Windows PowerShell solves that problem by allowing you to use counter sets. To see the available performance counter sets, use the <b>Get-Counter<\/b> cmdlet with the <b>listset<\/b><i> <\/i>parameter. In the following command I list the names of all the counter sets on my Windows 7 laptop. <\/p>\n<blockquote>\n<p>PS C:\\&gt; Get-Counter -ListSet * | Sort-Object CounterSetName | Select-Object CounterSetName<\/p>\n<p>CounterSetName<\/p>\n<p>&#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p>.NET CLR Data<\/p>\n<p>.NET CLR Networking<\/p>\n<p>.NET CLR Networking 4.0.0.0<\/p>\n<p>.NET Data Provider for Oracle<\/p>\n<p>.NET Data Provider for SqlServer<\/p>\n<p>.NET Memory Cache 4.0<\/p>\n<p>ASP.NET<\/p>\n<p>ASP.NET Applications<\/p>\n<p>ASP.NET Apps v4.0.30319<\/p>\n<p>ASP.NET State Service<\/p>\n<p>ASP.NET v4.0.30319<\/p>\n<p>Authorization Manager Applications<\/p>\n<p>BranchCache<\/p>\n<p>Browser<\/p>\n<p>Cache<\/p>\n<p>Client Side Caching<\/p>\n<p>Distributed Routing Table<\/p>\n<p>Event Tracing for Windows<\/p>\n<p>Event Tracing for Windows Session<\/p>\n<p>Fax Service<\/p>\n<p>Generic IKEv1, AuthIP, and IKEv2<\/p>\n<p>HTTP Service<\/p>\n<p>HTTP Service Request Queues<\/p>\n<p>HTTP Service URL Groups<\/p>\n<p>ICMP<\/p>\n<p>ICMPv6<\/p>\n<p>Internet Information Services Global<\/p>\n<p>IPHTTPS Global<\/p>\n<p>IPHTTPS Session<\/p>\n<p>IPsec AuthIP IPv4<\/p>\n<p>IPsec AuthIP IPv6<\/p>\n<p>IPsec Driver<\/p>\n<p>IPsec IKEv1 IPv4<\/p>\n<p>IPsec IKEv1 IPv6<\/p>\n<p>IPsec IKEv2 IPv4<\/p>\n<p>IPsec IKEv2 IPv6<\/p>\n<p>IPv4<\/p>\n<p>IPv6<\/p>\n<p>Job Object<\/p>\n<p>Job Object Details<\/p>\n<p>LogicalDisk<\/p>\n<p>Memory<\/p>\n<p>MSDTC Bridge 3.0.0.0<\/p>\n<p>MSDTC Bridge 4.0.0.0<\/p>\n<p>NBT Connection<\/p>\n<p>Netlogon<\/p>\n<p>Network Inspection System<\/p>\n<p>Network Interface<\/p>\n<p>Objects<\/p>\n<p>Offline Files<\/p>\n<p>OpsMgr Connector<\/p>\n<p>Pacer Flow<\/p>\n<p>Pacer Pipe<\/p>\n<p>Paging File<\/p>\n<p>Peer Name Resolution Protocol<\/p>\n<p>Per Processor Network Activity Cycles<\/p>\n<p>Per Processor Network Interface Card Activity<\/p>\n<p>PhysicalDisk<\/p>\n<p>Power Meter<\/p>\n<p>Print Queue<\/p>\n<p>Process<\/p>\n<p>Processor<\/p>\n<p>Processor Information<\/p>\n<p>RAS Port<\/p>\n<p>RAS Total<\/p>\n<p>ReadyBoost Cache<\/p>\n<p>Redirector<\/p>\n<p>Search Indexer<\/p>\n<p>Server<\/p>\n<p>Server Work Queues<\/p>\n<p>ServiceModelEndpoint 3.0.0.0<\/p>\n<p>ServiceModelEndpoint 4.0.0.0<\/p>\n<p>ServiceModelOperation 3.0.0.0<\/p>\n<p>ServiceModelOperation 4.0.0.0<\/p>\n<p>ServiceModelService 3.0.0.0<\/p>\n<p>ServiceModelService 4.0.0.0<\/p>\n<p>SMSvcHost 3.0.0.0<\/p>\n<p>SMSvcHost 4.0.0.0<\/p>\n<p>Synchronization<\/p>\n<p>System<\/p>\n<p>TBS counters<\/p>\n<p>TCPv4<\/p>\n<p>TCPv6<\/p>\n<p>Telephony<\/p>\n<p>Teredo Client<\/p>\n<p>Teredo Relay<\/p>\n<p>Teredo Server<\/p>\n<p>Terminal Services<\/p>\n<p>Terminal Services Session<\/p>\n<p>Thread<\/p>\n<p>UDPv4<\/p>\n<p>UDPv6<\/p>\n<p>USB<\/p>\n<p>WF (System.Workflow) 4.0.0.0<\/p>\n<p>WFP<\/p>\n<p>WFPv4<\/p>\n<p>WFPv6<\/p>\n<p>Windows Media Player Metadata<\/p>\n<p>Windows Workflow Foundation<\/p>\n<p>WSMan Quota Statistics<\/p>\n<\/blockquote>\n<p>Suppose I am interested in monitoring memory-related performance counters (something that you should probably consider anyway). I need to supply the path to the specific counter to the <b>Get-Counter<\/b> Windows PowerShell cmdlet in order to monitor the counter. The nice thing is that I do not have to know the path to the counter, nor do I need to type all of those paths. The reason is that I can retrieve the paths from the <b>memory<\/b> counter set. To do this I use dotted notation and retrieve the paths. Here is the command to do this.<\/p>\n<blockquote>\n<p>PS C:\\&gt; (get-Counter -ListSet memory).paths<\/p>\n<p>\\Memory\\Page Faults\/sec<\/p>\n<p>\\Memory\\Available Bytes<\/p>\n<p>\\Memory\\Committed Bytes<\/p>\n<p>\\Memory\\Commit Limit<\/p>\n<p>\\Memory\\Write Copies\/sec<\/p>\n<p>\\Memory\\Transition Faults\/sec<\/p>\n<p>\\Memory\\Cache Faults\/sec<\/p>\n<p>\\Memory\\Demand Zero Faults\/sec<\/p>\n<p>\\Memory\\Pages\/sec<\/p>\n<p>\\Memory\\Pages Input\/sec<\/p>\n<p>\\Memory\\Page Reads\/sec<\/p>\n<p>\\Memory\\Pages Output\/sec<\/p>\n<p>\\Memory\\Pool Paged Bytes<\/p>\n<p>\\Memory\\Pool Nonpaged Bytes<\/p>\n<p>\\Memory\\Page Writes\/sec<\/p>\n<p>\\Memory\\Pool Paged Allocs<\/p>\n<p>\\Memory\\Pool Nonpaged Allocs<\/p>\n<p>\\Memory\\Free System Page Table Entries<\/p>\n<p>\\Memory\\Cache Bytes<\/p>\n<p>\\Memory\\Cache Bytes Peak<\/p>\n<p>\\Memory\\Pool Paged Resident Bytes<\/p>\n<p>\\Memory\\System Code Total Bytes<\/p>\n<p>\\Memory\\System Code Resident Bytes<\/p>\n<p>\\Memory\\System Driver Total Bytes<\/p>\n<p>\\Memory\\System Driver Resident Bytes<\/p>\n<p>\\Memory\\System Cache Resident Bytes<\/p>\n<p>\\Memory\\% Committed Bytes In Use<\/p>\n<p>\\Memory\\Available KBytes<\/p>\n<p>\\Memory\\Available MBytes<\/p>\n<p>\\Memory\\Transition Pages RePurposed\/sec<\/p>\n<p>\\Memory\\Free &amp; Zero Page List Bytes<\/p>\n<p>\\Memory\\Modified Page List Bytes<\/p>\n<p>\\Memory\\Standby Cache Reserve Bytes<\/p>\n<p>\\Memory\\Standby Cache Normal Priority Bytes<\/p>\n<p>\\Memory\\Standby Cache Core Bytes<\/p>\n<\/blockquote>\n<p>So how do I use all these performance counter paths? The first thing I like to do is to store them into a variable, but that is not completely necessary because I can use the counter paths directly as shown here:<\/p>\n<blockquote>\n<p>Get-Counter -Counter (get-Counter -ListSet memory).paths<\/p>\n<\/blockquote>\n<p>The reason for storing the counter paths in a variable is so I can group them later. For now, I store the memory counter paths in a variable named <b>$memory<\/b>. I then use the <b>Get-Counter<\/b> cmdlet to retrieve an instance of the performance information for each of the counters in the variable. Truncated output of the process is shown here:<\/p>\n<blockquote>\n<p>PS C:\\&gt; $memory=(get-Counter -ListSet memory).paths<\/p>\n<p>PS C:\\&gt; Get-Counter -Counter $memory<\/p>\n<p>Timestamp CounterSamples<\/p>\n<p>&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p>1\/22\/2011 7:43:18 PM \\\\edwils1\\memory\\page faults\/sec :<\/p>\n<p>0<\/p>\n<p>\\\\edwils1\\memory\\available bytes :<\/p>\n<p>2671661056<\/p>\n<p>\\\\edwils1\\memory\\committed bytes :<\/p>\n<p>1656578048<\/p>\n<p>&lt;output truncated&gt;<\/p>\n<\/blockquote>\n<p>By default, the <b>Get-Counter<\/b> Windows PowerShell cmdlet retrieves a single instance of each of the counter&rsquo;s values. I can tell the cmdlet to retrieve multiple samples, and I can specify the interval between performance snapshots. The minimum interval between samples is one second. The maximum number of samples is 9223372036854775807 because <b>MaxSamples<\/b><i> <\/i>is a datatype of <b>int64<\/b>. Using the <b>MaxValue<\/b> static property of the <b>int64<\/b> class, I found out the maximum value. The code to do this is shown here: <\/p>\n<blockquote>\n<p>PS C:\\&gt; [int64]::MaxValue<\/p>\n<\/blockquote>\n<blockquote>\n<p>9223372036854775807<\/p>\n<\/blockquote>\n<p>Of course, if I really want to monitor a counter on a continuous basis, I use the <b>Continuous<\/b><i> <\/i>parameter. When I monitor a set of counters continuously, I use the Control+C keyboard shortcut to halt performance monitor collection and to return to the Windows PowerShell console. The command to do this is shown here:<\/p>\n<blockquote>\n<p>PS C:\\&gt; Get-Counter -Counter $memory -SampleInterval 1 -Continuous<\/p>\n<\/blockquote>\n<blockquote>\n<p>Timestamp CounterSamples<\/p>\n<p>&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p>1\/22\/2011 8:04:04 PM \\\\edwils1\\memory\\page faults\/sec :<\/p>\n<p>158.768772415052<\/p>\n<p>&lt;truncated&gt;<\/p>\n<\/blockquote>\n<p>If I want to parse the data I collect, I store the results into a variable. The command to take five samples at one-second intervals, using the memory performance counters, is shown here (remember that earlier I stored all the memory performance counter paths in the <b>$memory<\/b> variable): <\/p>\n<blockquote>\n<p>PS C:\\&gt; $counters = Get-Counter -Counter $memory -SampleInterval 1 -MaxSamples 5<\/p>\n<\/blockquote>\n<p>After I have the performance values stored in the <b>$counters<\/b> variable, I can parse the data by using standard Windows PowerShell techniques. The first thing to do is to find out which type of object I have stored in the variable, and to see which properties it exposes. To do this, I use the <b>Get-Member<\/b> cmdlet in the manner that appears here:<\/p>\n<blockquote>\n<p>PS C:\\&gt; $counters | Get-Member<\/p>\n<\/blockquote>\n<blockquote>\n<p>TypeName: Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSampleSet<\/p>\n<p>Name MemberType Definition<\/p>\n<p>&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<\/p>\n<p>Equals Method bool Equals(System.Object obj)<\/p>\n<p>GetHashCode Method int GetHashCode()<\/p>\n<p>GetType Method type GetType()<\/p>\n<p>ToString Method string ToString()<\/p>\n<p>CounterSamples Property Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample[&#8230;<\/p>\n<p>Timestamp Property System.DateTime Timestamp {get;set;}<\/p>\n<p>Readings ScriptProperty System.Object Readings {get=$strPaths = &#8220;&#8221;&#8230;<\/p>\n<\/blockquote>\n<p>This information tells me two things. The first is that I am dealing with a collection of data (I kind of figured that because I took five different readings at one-second intervals). The second thing I see is more significant, and that is that there is a property called <b>CounterSamples<\/b>, and it is a rich object as indicated by the <b>Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample[&#8230;<\/b> property type information. Because I have a collection to deal with, it means that I will need to select an individual performance sample to work with. I can pipe the <b>$Counters<\/b> variable to the <b>Foreach-Object<\/b> cmdlet, or I can use the <b>Foreach <\/b>statement and walk through the data, or I can index into the collection. While I am still exploring, I will index into the collection and explore the <b>CounterSamples<\/b><i> <\/i>property<i> <\/i>as illustrated here:<\/p>\n<blockquote>\n<p>PS C:\\&gt; $counters[0].CounterSamples | Get-Member<\/p>\n<p>TypeName: Microsoft.PowerShell.Commands.GetCounter.PerformanceCounterSample<\/p>\n<p>Name MemberType Definition<\/p>\n<p>&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<\/p>\n<p>Equals Method bool Equals(System.Object obj)<\/p>\n<p>GetHashCode Method int GetHashCode()<\/p>\n<p>GetType Method type GetType()<\/p>\n<p>ToString Method string ToString()<\/p>\n<p>CookedValue Property System.Double CookedValue {get;set;}<\/p>\n<p>CounterType Property System.Diagnostics.PerformanceCounterType CounterType {get;set;}<\/p>\n<p>DefaultScale Property System.UInt32 DefaultScale {get;set;}<\/p>\n<p>InstanceName Property System.String InstanceName {get;set;}<\/p>\n<p>MultipleCount Property System.UInt32 MultipleCount {get;set;}<\/p>\n<p>Path Property System.String Path {get;set;}<\/p>\n<p>RawValue Property System.UInt64 RawValue {get;set;}<\/p>\n<p>SecondValue Property System.UInt64 SecondValue {get;set;}<\/p>\n<p>Status Property System.UInt32 Status {get;set;}<\/p>\n<p>TimeBase Property System.UInt64 TimeBase {get;set;}<\/p>\n<p>Timestamp Property System.DateTime Timestamp {get;set;}<\/p>\n<p>Timestamp100NSec Property System.UInt64 Timestamp100NSec {get;set;}<\/p>\n<\/blockquote>\n<p>The information that appears is standard performance counter type of information. The displayed properties bear a strong resemblance to the properties of the WMI performance counter classes. I like the cooked values, the path, and the time stamp. I sort by the path to group my counters together, and then wrap the table in case any paths are too long. The percentage sign (<b>%<\/b>) is an alias for the <b>Foreach-Object<\/b> cmdlet, <b>sort<\/b> is an alias for the <b>Sort-Object<\/b> cmdlet, and <b>ft<\/b> is an alias for the <b>Format-Table<\/b> cmdlet. The command to select the data I am interested in examining appears here.<\/p>\n<blockquote>\n<p>$counters | % { $_.counterSamples } | sort path | ft timestamp, path, cookedvalue -Wrap &ndash;AutoSize<\/p>\n<\/blockquote>\n<p>When the previous command runs, the output shown in the following image appears.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/0333.hsg-1-31-11-1_02BD5F78.jpg\"><img decoding=\"async\" height=\"404\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/8267.hsg-1-31-11-1_thumb_26961105.jpg\" alt=\"Image of script output\" border=\"0\" title=\"Image of script output\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>AC, that is all there is to getting started with using the <b>Get-Counter<\/b> Windows PowerShell cmdlet. Performance Week will continue tomorrow when I will talk about additional ways of using the <b>Get-Counter<\/b> cmdlet. <\/p>\n<p>I invite you to follow me on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp;Summary: Learn how to use Windows PowerShell to simplify collecting performance information from your servers. Hey, Scripting Guy! We are having performance problems with several of our servers. It is really strange, because if you were to look at the specifications, you would think they are awesome boxes. What I need to do is to [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,60,3,45],"class_list":["post-15741","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-operating-system","tag-performance","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp;Summary: Learn how to use Windows PowerShell to simplify collecting performance information from your servers. Hey, Scripting Guy! We are having performance problems with several of our servers. It is really strange, because if you were to look at the specifications, you would think they are awesome boxes. What I need to do is to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/15741","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=15741"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/15741\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=15741"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=15741"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=15741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}