或者 perfmon 是否应该限于具有模拟生产活动的负载测试的 Dev/QA 服务器?
我想运行 perfmon 两天(就像 Sql Server 大师 Brent Ozar 建议的那样) 来全面了解我的 Web 应用程序的数据库性能。
答案1
SQL Server 和大多数其他产品始终生成计数器,无论是否有侦听器(忽略 -x 启动选项)。计数器跟踪对受监视的应用程序完全透明。有一个共享内存区域,受监视的应用程序可在该区域写入数据,而监视会话可从该区域以指定的间隔读取原始值。因此,与监视相关的唯一成本是监视过程的成本以及将采样值写入磁盘的成本。选择合适的收集间隔(我通常选择 15 秒)和适中的计数器数量(50-100),并写入二进制文件格式通常不会对受监视的系统产生影响。
但我建议不要使用 Perfmon(如 perfmon.exe)。相反,你应该熟悉 logman.exe,请参阅Logman.exe、Relog.exe 和 Typeperf.exe 工具的说明。这样,您就不会将收集会话绑定到您的会话。Logman 是一个命令行工具,可用于脚本和计划作业中以启动和停止收集会话。
答案2
在生产机器上运行 perfmon 并没有什么问题。它相对低调,可以为您收集大量有用信息。如果您不在生产服务器上运行一些分析,您将如何准确模拟生产负载?来自 Brent Ozar 在您自己的链接中:
让 Perfmon 运行一两天,以收集服务器活动的良好基线。它对被监控的 SQL Server 的侵入性不大,而且深入的结果将带来回报。我们拥有的数据越多,我们在分析 Perfmon 结果方面就能做得越好。
我已经在大量生产 Exchange 箱上运行了 perfmon,没有任何不良影响。
答案3
自从我听了克林特·霍夫曼, 谁写的朋友一个用于分析 Perfmon 日志的实用程序,在一次播客中介绍过。我已经在我们所有的生产应用程序服务器上设置了我称之为 Flight Recorder 的东西。这种做法对于诊断问题和监控趋势非常有用。
下面是我用来设置自动启动的 Perfmon Collector 的脚本,带有日志清除功能。如果需要,可以向其输入一个列出要收集的性能计数器的文件(每行一个)或一个 PAL Threshold XML 文件。我喜欢使用 PAL Threshold 文件。
<#
Install-FlightRecorder.ps1
.SYNOPSIS
Installs or sets up the pieces necessary to create PerfMon Collector
snapshots, one a minute, to a file located in C:\FlightRecorder.
.DESCRIPTION
Installs or sets up the pieces necessary to create PerfMon Collector
snapshots, one a minute, to a file located in C:\FlightRecorder.
.PARAMETER Path
File listing performance counters to collect, one per line.
Or a PAL Threshold XML file.
#>
[CmdletBinding()]
param (
[string]$Path
)
#Requires -RunAsAdministrator
$ScriptDir = { Split-Path $MyInvocation.ScriptName –Parent }
$DeleteTempFile = $False
function Main {
if (-not $Path) { $Path = DefaultFile $Path }
if (-not (Test-Path $Path)) {
Write-Warning "Path does not exist or is inaccessable: $Path"
Exit 1
}
if ($Path -like '*.xml') { $Path = PALFile $Path }
Install-FlightRecorder
if ($Path.startswith($env:TEMP)) {Remove-Item $Path}
Write-Verbose 'Installation Successful.'
}
function Install-FlightRecorder {
Write-Verbose 'Setting up the Flight Recorder.'
if (-not (Test-Path c:\FlightRecorder\)) {
mkdir c:\FlightRecorder | out-null
}
if ((LOGMAN query) -match 'FlightRecorder') {
Write-Verbose 'Removing former FlightRecorder PerfMon Collector.'
LOGMAN stop FlightRecorder | out-null
LOGMAN delete FlightRecorder | Write-Verbose
}
Write-Verbose 'Creating FlightRecorder PerfMon Collector.'
LOGMAN create counter FlightRecorder -o "C:\FlightRecorder\FlightRecorder_$env:computername" -cf $Path -v mmddhhmm -si 00:01:00 -f bin | Write-Verbose
SCHTASKS /Create /TN FlightRecorder-Nightly /F /SC DAILY /ST 00:00 /RU SYSTEM /TR 'powershell.exe -command LOGMAN stop FlightRecorder; LOGMAN start FlightRecorder; dir c:\FlightRecorder\*.blg |?{ $_.LastWriteTime -lt (Get-Date).AddDays(-3)} | del' | Write-Verbose
SCHTASKS /Create /TN FlightRecorder-Startup /F /SC ONSTART /RU SYSTEM /TR "LOGMAN start FlightRecorder" | Write-Verbose
SCHTASKS /Run /TN FlightRecorder-Startup | Write-Verbose
}
function DefaultFile {
Write-Warning 'Counter or PAL file not specified, using default configuration.'
$DeleteTempFile = $True
$Path = [System.IO.Path]::GetTempFileName()
Set-Content -Encoding ASCII $Path @'
\LogicalDisk(*)\Avg. Disk sec/Read
\LogicalDisk(*)\Avg. Disk sec/Write
\LogicalDisk(*)\Disk Transfers/sec
\LogicalDisk(C:)\Free Megabytes
\Memory\% Committed Bytes In Use
\Memory\Available MBytes
\Memory\Committed Bytes
\Memory\Free System Page Table Entries
\Memory\Pages Input/sec
\Memory\Pages/sec
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Bytes
\Memory\System Cache Resident Bytes
\Network Interface(*)\Bytes Total/sec
\Network Interface(*)\Output Queue Length
\Paging File(*)\% Usage
\Paging File(*)\% Usage Peak
\PhysicalDisk(*)\Avg. Disk sec/Read
\PhysicalDisk(*)\Avg. Disk sec/Write
\Process(_Total)\Handle Count
\Process(_Total)\Private Bytes
\Process(_Total)\Thread Count
\Process(_Total)\Working Set
\Processor(*)\% Interrupt Time
\Processor(*)\% Privileged Time
\Processor(*)\% Processor Time
\System\Context Switches/sec
\System\Processor Queue Length
'@
$Path
}
function PalFile {
$DeleteTempFile = $True
$InputPath = $Path
$Path = [System.IO.Path]::GetTempFileName()
$filesRead = @()
Read-PalFile $InputPath | Select -Unique | sort | Set-Content -Encoding ASCII $Path
$Path
}
$script:filesRead =@()
function Read-PalFile ([string]$path) {
if (-not (Test-Path $path)) {
Write-Warning "PAL Threshold file not found: $path"
return
}
if ($script:filesRead -contains $path) {return}
$script:filesRead += @($path)
Write-Verbose "Reading PAL Threshold file: $path"
$xml = [XML](Get-Content $path)
$xml.SelectNodes('//DATASOURCE[@TYPE="CounterLog"]') | select -expand EXPRESSIONPATH
$xml.SelectNodes('//INHERITANCE/@FILEPATH') | select -expand '#text' | where {$_ } | ForEach {
$newpath = Join-Path (Split-Path -parent $path) $_
Write-Debug "Inheritance file: $newpath"
Read-PalFile $newpath
}
}
. Main
答案4
在理想情况下,生产服务器完全反映了开发服务器的工作方式,并且是开发服务器的完全副本,因此生产服务器上永远不需要 perfmon,因为结果将与开发服务器上的结果相同。当然,这种虚构的情况永远不会发生,所以我们确实需要在生产服务器上运行 perfmon,这绝对没有错。除此之外,我们可能需要使用 perfmon 和其他工具来了解生产服务器的行为为何与开发服务器不同。