我正在尝试在区域(这是一个文件夹)内使用此逻辑搜索文件并显示它们。问题是,当文件很多(例如 200k)时,搜索需要大约 10 分钟,而在文件不多的文件夹中,搜索速度非常快。加快搜索速度的最佳方法是什么?我也尝试过使用运行空间,但没有成功,搜索时间根本没有改变。
我正在使用 Powershell 版本 5.1.22621.4249
$buttonSearch.Add_Click({
$region = $comboBoxRegion.Text
$payIDRange = $textBoxPayID.Text
$checkNumRange = $textBoxCheckNum.Text
$checkDateRange = $textBoxCheckDate.Text
if ([string]::IsNullOrWhiteSpace($global:selectedFolder)) {
[System.Windows.Forms.MessageBox]::Show("Please choose a folder before searching.")
return
}
if ([string]::IsNullOrWhiteSpace($region)) {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("Please select a region.")
return
}
if ([string]::IsNullOrWhiteSpace($payIDRange) -or $payIDRange -notmatch "^\d+-\d+$") {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("Invalid Pay ID range.")
return
}
$global:totalResults = New-Object System.Collections.Generic.List[object]
$payIDStart, $payIDEnd = $payIDRange -split "-", 2
$payIDStart = [int]$payIDStart
$payIDEnd = [int]$payIDEnd
$allFiles = Get-ChildItem -Path "$global:selectedFolder\$region" -File
foreach ($file in $allFiles) {
$fileInfo = Convert-FileName -fileName $file.Name
if ($fileInfo -ne $null) {
$extractedPayerID = [int]$fileInfo.PayerID
$payIDValid = $extractedPayerID -ge $payIDStart -and $extractedPayerID -le $payIDEnd
$checkNumValid = $true
if ($checkNumRange -ne "") {
$checkNumStart, $checkNumEnd = $checkNumRange -split "-", 2
$checkNumValid = $fileInfo.CheckNum -ge [int]$checkNumStart -and $fileInfo.CheckNum -le [int]$checkNumEnd
}
$checkDateValid = $true
if ($checkDateRange -ne "") {
$startDate, $endDate = $checkDateRange -split " - ", 2
$startDate = [datetime]::ParseExact($startDate.Trim(), "yyyy-MM-dd", $null)
$endDate = [datetime]::ParseExact($endDate.Trim(), "yyyy-MM-dd", $null)
$checkDateValid = $fileInfo.CheckDate -ge $startDate -and $fileInfo.CheckDate -le $endDate
}
if ($payIDValid -and $checkNumValid -and $checkDateValid) {
$resultObject = New-Object -TypeName PSObject -Property @{
Name = $file.Name
Path = $file.FullName
}
$global:totalResults.Add($resultObject)
}
}
}
if ($global:totalResults.Count -eq 0) {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("No results found.")
return
}
$global:currentPage = 0
Show-Results
})
我尝试添加运行空间来执行更快的搜索,但没有成功。
$buttonSearch.Add_Click({
$region = $comboBoxRegion.Text
$payIDRange = $textBoxPayID.Text
$checkNumRange = $textBoxCheckNum.Text
$checkDateRange = $textBoxCheckDate.Text
if ($global:selectedFolder -eq "") {
[System.Windows.Forms.MessageBox]::Show("Please choose a folder before searching.")
return
}
if ($region -eq "") {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("Please select a region.")
return
}
if ($payIDRange -eq "" -or $payIDRange -notmatch "^\d+-\d+$") {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("Invalid Pay ID range.")
return
}
$results = Search-Files -selectedFolder $global:selectedFolder -region $region -payIDRange $payIDRange -checkNumRange $checkNumRange -checkDateRange $checkDateRange
if ($results.Count -eq 0) {
$dataGridView.Rows.Clear()
[System.Windows.Forms.MessageBox]::Show("No results found.")
return
}
$global:totalResults = $results
$global:currentPage = 0
Show-Results
})
$buttonView.Add_Click({
$selectedFiles = $global:selectedFiles
if ($selectedFiles.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("No files selected for viewing.")
return
}
$viewForm = New-Object System.Windows.Forms.Form
$viewForm.Text = "View eClaims"
$viewForm.Size = New-Object System.Drawing.Size(800, 600)
$viewForm.FormBorderStyle = 'FixedDialog'
$viewForm.BackColor = [System.Drawing.Color]::FromArgb(240, 240, 240)
$tabControl = New-Object System.Windows.Forms.TabControl
$tabControl.Dock = [System.Windows.Forms.DockStyle]::Fill
$tabControl.Font = New-Object System.Drawing.Font("Segoe UI", 12, [System.Drawing.FontStyle]::Regular)
foreach ($fileName in $selectedFiles) {
$tabPage = New-Object System.Windows.Forms.TabPage
$tabPage.Text = $fileName
$tabPage.BackColor = [System.Drawing.Color]::White
$tableLayoutPanel = New-Object System.Windows.Forms.TableLayoutPanel
$tableLayoutPanel.Dock = [System.Windows.Forms.DockStyle]::Fill
$tableLayoutPanel.ColumnCount = 1
$tableLayoutPanel.RowCount = 2
$tableLayoutPanel.Padding = New-Object System.Windows.Forms.Padding(10)
$tableLayoutPanel.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::AutoSize)))
$tableLayoutPanel.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Percent, 100)))
$headerLabel = New-Object System.Windows.Forms.Label
$headerLabel.Text = "Content of " + $fileName
$headerLabel.Font = New-Object System.Drawing.Font("Segoe UI", 14, [System.Drawing.FontStyle]::Bold)
$headerLabel.Dock = [System.Windows.Forms.DockStyle]::Top
$headerLabel.AutoSize = $true
$headerLabel.ForeColor = [System.Drawing.Color]::FromArgb(60, 179, 113)
# Create a RichTextBox to display file content
$richTextBox = New-Object System.Windows.Forms.RichTextBox
$richTextBox.ReadOnly = $true
$richTextBox.Dock = [System.Windows.Forms.DockStyle]::Fill
$richTextBox.Font = New-Object System.Drawing.Font("Courier New", 10, [System.Drawing.FontStyle]::Regular)
$richTextBox.BackColor = [System.Drawing.Color]::White
$richTextBox.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
# Load the content of the file
$filePath = ($global:totalResults | Where-Object { $_.Name -eq $fileName }).Path
if (-not [string]::IsNullOrEmpty($filePath) -and (Test-Path $filePath)) {
$richTextBox.Text = Get-Content -Path $filePath -Raw
} else {
$richTextBox.Text = "File not found: $fileName"
}
# Add controls to the TableLayoutPanel
$tableLayoutPanel.Controls.Add($headerLabel, 0, 0)
$tableLayoutPanel.Controls.Add($richTextBox, 0, 1)
$tabPage.Controls.Add($tableLayoutPanel)
$tabControl.TabPages.Add($tabPage)
}
$viewForm.Controls.Add($tabControl)
$viewForm.ShowDialog()
})
一般来说,为了提高性能,您应该尽量减少任何循环中的计算。 您的
foreach()
循环内有一些代码不需要:
$startDate, $endDate = $checkDateRange -split " - ", 2
$startDate = [datetime]::ParseExact($startDate.Trim(), "yyyy-MM-dd", $null)
$endDate = [datetime]::ParseExact($endDate.Trim(), "yyyy-MM-dd", $null)
$startDate
和 $endDate
每个文件都不会更改。
在 foreach
循环之前初始化它们。
你的第二次尝试也是如此,但更糟糕。为每个匹配文件添加一个选项卡可能会导致您的 UI 消耗过多的内存和处理器时间,同时变得难以使用。我不知道运行空间是在哪里实现的,也不知道它有什么帮助。您的第一次尝试就走在正确的轨道上:收集您需要的所有文件和信息,然后呈现数据。在处理过程中构建 UI 会很慢。
您可能会选择在您希望长时间运行的代码周围放置一些 Measure-Command 块。另请参阅这篇文章,了解各种变量类型的 Powershell 性能。
优化时的经验法则:尽量让循环中执行的代码尽可能小、快,并尽量让循环执行次数尽可能少。