В настоящее время я работаю над скриптом PowerShell, который будет использоваться в TeamCity как часть шага сборки. Сценарий должен:Производительность файлов чтения скриптов PowerShell слишком медленная
- рекурсивно проверить все файлы с определенным расширением (.item) в папке,
- читать третью строку каждого файла (который содержит GUID) и проверьте, есть ли дубликаты в этих строках,
- войти путь к файлу, который содержит дубликат GUID и журнал самого GUID,
- сделать TeamCity сборки потерпеть неудачу, если один или несколько дубликатов найдены
Я совершенно новый для ПОЛНОМОЧИЯ ад скрипты, но до сих пор я сделал что-то, что делает то, что я ожидаю, что это сделать:
Write-Host "Start checking for Unicorn serialization errors."
$files = get-childitem "%system.teamcity.build.workingDir%\Sitecore\serialization" -recurse -include *.item | where {! $_.PSIsContainer} | % { $_.FullName }
$arrayOfItemIds = @()
$NrOfFiles = $files.Length
[bool] $FoundDuplicates = 0
Write-Host "There are $NrOfFiles Unicorn item files to check."
foreach ($file in $files)
{
$thirdLineOfFile = (Get-Content $file)[2 .. 2]
if ($arrayOfItemIds -contains $thirdLineOfFile)
{
$FoundDuplicates = 1
$itemId = $thirdLineOfFile.Split(":")[1].Trim()
Write-Host "Duplicate item ID found!"
Write-Host "Item file path: $file"
Write-Host "Detected duplicate ID: $itemId"
Write-Host "-------------"
Write-Host ""
}
else
{
$arrayOfItemIds += $thirdLineOfFile
}
}
if ($foundDuplicates)
{
"##teamcity[buildStatus status='FAILURE' text='One or more duplicate ID's were detected in Sitecore serialised items. Check the build log to see which files and ID's are involved.']"
exit 1
}
Write-Host "End script checking for Unicorn serialization errors."
Проблема в том, что это очень медленно! Папка, которая должна быть проверена этим скриптом, в настоящее время содержит более 14 000 файлов .item, и очень вероятно, что эта сумма будет только расти в будущем. Я понимаю, что открытие и чтение большого количества файлов - это обширная операция, но я не ожидал, что это займет примерно полчаса. Это слишком долго, потому что это означает, что время сборки для каждой (моментальной) сборки будет увеличено на полчаса, что неприемлемо. Я надеялся, что сценарий завершится через пару минут максимум.
Я не могу поверить, что для этого не существует более быстрого подхода .. так что любая помощь в этой области очень ценится!
Решение
Ну, я должен сказать, что все 3 ответов я получил до сих пор помогли мне в этом. Сначала я начал использовать классы .NET Framework, а затем использовал словарь, чтобы решить проблему растущего массива. Время, затрачиваемое на запуск моего собственного скрипта, составляло около 30 минут, а затем это заняло всего 2 минуты, используя классы .NET framework. После использования решения для словаря, он снизился всего на 6 или 7 секунд! Окончательный сценарий, который я использую:
Write-Host "Start checking for Unicorn serialization errors."
[String[]] $allFilePaths = [System.IO.Directory]::GetFiles("%system.teamcity.build.workingDir%\Sitecore\serialization", "*.item", "AllDirectories")
$IdsProcessed = New-Object 'system.collections.generic.dictionary[string,string]'
[bool] $FoundDuplicates = 0
$NrOfFiles = $allFilePaths.Length
Write-Host "There are $NrOfFiles Unicorn item files to check."
Write-Host ""
foreach ($filePath in $allFilePaths)
{
[System.IO.StreamReader] $sr = [System.IO.File]::OpenText($filePath)
$unused1 = $sr.ReadLine() #read the first unused line
$unused2 = $sr.ReadLine() #read the second unused line
[string]$thirdLineOfFile = $sr.ReadLine()
$sr.Close()
if ($IdsProcessed.ContainsKey($thirdLineOfFile))
{
$FoundDuplicates = 1
$itemId = $thirdLineOfFile.Split(":")[1].Trim()
$otherFileWithSameId = $IdsProcessed[$thirdLineOfFile]
Write-Host "---------------"
Write-Host "Duplicate item ID found!"
Write-Host "Detected duplicate ID: $itemId"
Write-Host "Item file path 1: $filePath"
Write-Host "Item file path 2: $otherFileWithSameId"
Write-Host "---------------"
Write-Host ""
}
else
{
$IdsProcessed.Add($thirdLineOfFile, $filePath)
}
}
if ($foundDuplicates)
{
"##teamcity[buildStatus status='FAILURE' text='One or more duplicate ID|'s were detected in Sitecore serialised items. Check the build log to see which files and ID|'s are involved.']"
exit 1
}
Write-Host "End script checking for Unicorn serialization errors. No duplicate ID's were found."
Так что спасибо всем!
Возможно, вы ограничены здесь IO-пропускной способностью. Таким образом, основное время (вероятно) используется при перетаскивании файлов с диска. Если это так (и подсчет конверта должен быть в состоянии подтвердить его), то самым простым способом ускорить его было бы перейти на более быстрое хранилище - например, SSD. –
@Mike Wise: Возможно, это было, хотя полчаса даже для копирования 14000 файлов были бы чрезмерными на любой современной машине. Я думаю, что в этом случае файл IO не является проблемой вообще. Поскольку его код является «частью шага сборки», все файлы будут обрабатываться или создаваться непосредственно перед его запуском кода и, следовательно, все еще будут в кеше диска. –