Ускорение сборки таблицы

Ответить
Karen
Сообщения: 12
Зарегистрирован: 20 авг 2021, 10:34
Поблагодарили: 1 раз

Ускорение сборки таблицы

Сообщение Karen »

Доброго дня! Есть код, который собирает таблицу из данных, которые хранятся в .json файлах. Файлов ~500 Штук, в каждом из них информация по сотруднику (1-10 блоков). Данный код собирает таблицу за 3 минуты. Есть варианты ускорения? Пробовал workflow и foreach -parallel (безуспешно):

Wake up, Neo, select all

$table_name = 'Data'
$global:table = New-Object system.Data.DataTable '$table_name'
$column1 = New-Object system.Data.DataColumn ID
$column2 = New-Object system.Data.DataColumn Login
$column3 = New-Object system.Data.DataColumn Name
$column4 = New-Object system.Data.DataColumn Lastname
$column5 = New-Object system.Data.DataColumn Patronymic
$column6 = New-Object system.Data.DataColumn Fullname
$column7 = New-Object system.Data.DataColumn Email
$column8 = New-Object system.Data.DataColumn Datecreated
$column9 = New-Object system.Data.DataColumn Position
$column10 = New-Object system.Data.DataColumn Company
$column11 = New-Object system.Data.DataColumn Manager
$column12 = New-Object system.Data.DataColumn Phone
$column13 = New-Object system.Data.DataColumn Block
$column14 = New-Object system.Data.DataColumn Practice
$column15 = New-Object system.Data.DataColumn Birthday
$table.columns.add($column1)
$table.columns.add($column2)
$table.columns.add($column3)
$table.columns.add($column4)
$table.columns.add($column5)
$table.columns.add($column6)
$table.columns.add($column7)
$table.columns.add($column8)
$table.columns.add($column9)
$table.columns.add($column10)
$table.columns.add($column11)
$table.columns.add($column12)
$table.columns.add($column13)
$table.columns.add($column14)
$table.columns.add($column15)
$jsons=get-childitem "C:\Scripts\Synchronization_with_Intranet\base" -file
foreach ($json in $jsons) {
$temp=Get-Content $json.fullname | ConvertFrom-json
$count = $temp.data.count
0..($count-1) | foreach {
$ID=$temp[$_].id
$login=($temp[$_].meta | convertfrom-json).login
$name=$temp[$_].name
$lastname=$temp[$_].last_name
$patronymic=$temp[$_].patronymic
$fullname=$temp[$_].last_name+' '+$temp[$_].name+' '+$temp[$_].patronymic
$position=($temp[$_].meta | convertfrom-json).position
$email=$temp[$_].email
$datecreated='{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($temp[$_].created_at)")
$company=($temp[$_].companies | where {$_.is_default -eq 'true'}).name
$manager=$temp[$_].manager.last_name+' '+$temp[$_].manager.name+' '+$temp[$_].manager.patronymic
if ($temp[$_].phones.count -eq 1) {
$phone=$temp[$_].phones.phone
}
if ($temp[$_].phones.count -eq 0) {
$phone='-'
}
if ($temp[$_].phones.count -gt 1) {
$phone=($temp[$_].phones | where {$_.type.title -eq 'корпоративный'}).phone
}
$block=($temp[$_].meta | convertfrom-json).blockname
$practice=($temp[$_].meta | convertfrom-json).practice
$a=(($temp[$_].meta | convertfrom-json).birthday -split '-')
$birthday="$($a[2]).$($a[1]).$($a[0])"
$row = $table.NewRow()
$row.ID=$ID
$row.Login=$login
$row.Name=$name
$row.Lastname=$lastname
$row.Patronymic=$patronymic
$row.Fullname=$fullname
$row.Position=$position
$row.Email=$email
$row.Datecreated=$datecreated
$row.Company=$company
$row.Manager=$manager
$row.Phone=$phone
$row.Block=$block
$row.Practice=$practice
$row.Birthday=$birthday
$table.Rows.Add($row)
}
}
Аватара пользователя
Fors1k
Администратор
Сообщения: 57
Зарегистрирован: 08 июн 2021, 17:23
Благодарил (а): 4 раза
Поблагодарили: 3 раза

Re: Ускорение сборки таблицы

Сообщение Fors1k »

Привет! Вот так можно распараллелить работу:

Wake up, Neo, select all

cls
$path = "C:\Scripts\Synchronization_with_Intranet\base"

$jsonToTable = {param($json)
$table_name = 'Employees'
$table = New-Object system.Data.DataTable $table_name
$columns = @(
New-Object system.Data.DataColumn ID
New-Object system.Data.DataColumn Login
New-Object system.Data.DataColumn Name
New-Object system.Data.DataColumn Lastname
New-Object system.Data.DataColumn Patronymic
New-Object system.Data.DataColumn Fullname
New-Object system.Data.DataColumn Email
New-Object system.Data.DataColumn Datecreated
New-Object system.Data.DataColumn Position
New-Object system.Data.DataColumn Company
New-Object system.Data.DataColumn Manager
New-Object system.Data.DataColumn Phone
New-Object system.Data.DataColumn Block
New-Object system.Data.DataColumn Practice
New-Object system.Data.DataColumn Birthday
)
$columns|ForEach{$table.Columns.Add($_)}

$temp = Get-Content $json.fullname | ConvertFrom-json
$count = $temp.data.count

$temp|ForEach{
$ID = $_.id
$login = ($_.meta | convertfrom-json).login
$name = $_.name
$lastname = $_.last_name
$patronymic = $_.patronymic
$fullname = $_.last_name+' '+$_.name+' '+$_.patronymic
$position = ($_.meta | convertfrom-json).position
$email = $_.email
$datecreated = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
$company = ($_.companies | where {$_.is_default -eq 'true'}).name
$manager = $_.manager.last_name+' '+$_.manager.name+' '+$_.manager.patronymic
if ($_.phones.count -eq 1) {
$phone = $_.phones.phone
}
if ($_.phones.count -eq 0) {
$phone = '-'
}
if ($_.phones.count -gt 1) {
$phone = ($_.phones | where {$_.type.title -eq 'корпоративный'}).phone
}
$block = ($_.meta | convertfrom-json).blockname
$practice = ($_.meta | convertfrom-json).practice
$a = (($_.meta | convertfrom-json).birthday -split '-')
$birthday = "$($a[2]).$($a[1]).$($a[0])"

$row = $table.NewRow()
$row.ID = $ID
$row.Login = $login
$row.Name = $name
$row.Lastname = $lastname
$row.Patronymic = $patronymic
$row.Fullname = $fullname
$row.Position = $position
$row.Email = $email
$row.Datecreated = $datecreated
$row.Company = $company
$row.Manager = $manager
$row.Phone = $phone
$row.Block = $block
$row.Practice = $practice
$row.Birthday = $birthday
$table.Rows.Add($row)
}
return ,$table
}

$jsons = Get-ChildItem $path -file
$n = [Environment]::ProcessorCount

foreach ($json in $jsons) {
Start-ThreadJob -name jsonRead $jsonToTable -ArgumentList ($json) -ThrottleLimit $n -StreamingHost $Host
}

while($true){
try{$jobs = Get-Job -Name jsonRead -ea Stop}catch{break}

$j = $jobs|where{$_.HasMoreData -and $_.State -eq "Completed"}|select -First 1
$get = $j|Receive-Job
if($get){
if(!$table){$table = $get.Copy();$j|Remove-Job;continue}
$table.Merge($get)
$get = $null
$j|Remove-Job
}
sleep -m 2
}

$table|Out-GridView
Аватара пользователя
Fors1k
Администратор
Сообщения: 57
Зарегистрирован: 08 июн 2021, 17:23
Благодарил (а): 4 раза
Поблагодарили: 3 раза

Re: Ускорение сборки таблицы

Сообщение Fors1k »

Пример для теста.

Создадим несколько Json файлов

Wake up, Neo, select all

cls
$path = "$env:TEMP\testjson"

$json_1 = @(
@{time = 11;name = "aa"}
@{time = 22;name = "bb"}
)

$json_2 = @(
@{time = 33;name = "cc"}
@{time = 44;name = "dd"}
)

$json_3 = @(
@{time = 55;name = "ee"}
@{time = 66;name = "ff"}
)

$json_1, $json_2, $json_3|ForEach{$i = 1}{
$_|ConvertTo-Json|Out-File (New-Item "$path\$i.json" -Force) -Encoding UTF8
$i++
}

Прочитаем файлы параллельно и занесем их данные в одну таблицу

Wake up, Neo, select all

cls
$path = "$env:TEMP\testjson"

$jsonToTable = {param($json)
$table_name = 'Employees'
$table = New-Object system.Data.DataTable $table_name
$columns = @(
New-Object system.Data.DataColumn time
New-Object system.Data.DataColumn name
)
$columns|ForEach{$table.Columns.Add($_)}

$temp = Get-Content $json.fullname | ConvertFrom-json
$count = $temp.count

$temp|ForEach{
$time = $_.time
$name = $_.name

$row = $table.NewRow()
$row.time = $time
$row.name = $name
$table.Rows.Add($row)
}
return ,$table
}

$jsons = Get-ChildItem $path -file
$n = [Environment]::ProcessorCount

foreach ($json in $jsons) {
Start-ThreadJob -name jsonRead $jsonToTable -ArgumentList ($json) -ThrottleLimit $n -StreamingHost $Host
}

while($true){
try{$jobs = Get-Job -Name jsonRead -ea Stop}catch{break}

$j = $jobs|where{$_.HasMoreData -and $_.State -eq "Completed"}|select -First 1
$get = $j|Receive-Job
if($get){
if(!$table){$table = $get.Copy();$j|Remove-Job;continue}
$table.Merge($get)
$get = $null
$j|Remove-Job
}
sleep -m 2
}

$table|Out-GridView

Output


time name
---- ----
11   aa
22   bb
33   cc
44   dd
55   ee
66   ff
Karen
Сообщения: 12
Зарегистрирован: 20 авг 2021, 10:34
Поблагодарили: 1 раз

Re: Ускорение сборки таблицы

Сообщение Karen »

Спасибо, с этим кодом пошустрее конечно таблица собирается, но есть одна проблема. Строка на powershell 7 не отрабатывает:

Wake up, Neo, select all

$datecreated = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")

$_.created_at вроде бы стандартный формат времени. Например, 2018-05-11T01:29:16+03:00
В powershell 5 проблем не возникает

Аватара пользователя
Fors1k
Администратор
Сообщения: 57
Зарегистрирован: 08 июн 2021, 17:23
Благодарил (а): 4 раза
Поблагодарили: 3 раза

Re: Ускорение сборки таблицы

Сообщение Fors1k »

Какую-то ошибку пишет, или просто поле остается пустым?

Wake up, Neo, select all

$date = "2018-05-11T01:29:16+03:00"
$dateCreated = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse($date)
$dateCreated

Выполнил и в 5.1 и в 7.1.3, код сработал: 11.05.2018.

Вот еще такой вариант записи есть:

Wake up, Neo, select all

$date = "2018-05-11T01:29:16+03:00"
$dateCreated = Get-Date -Date $date -Format "dd.MM.yyyy"
$dateCreated
Karen
Сообщения: 12
Зарегистрирован: 20 авг 2021, 10:34
Поблагодарили: 1 раз

Re: Ускорение сборки таблицы

Сообщение Karen »

Да, ошибка:

Wake up, Neo, select all

Line |
35 | … d = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
| ~~~~~~~~~~~~~
| Exception calling "Parse" with "1" argument(s): "String '03/17/2020 00:22:51' was not recognized as a valid DateTime."
MethodInvocationException:
Line |
35 | … d = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
| ~~~~~~~~~~~~~
| Exception calling "Parse" with "1" argument(s): "String '07/28/2020 10:20:03' was not recognized as a valid DateTime."
MethodInvocationException:
Line |
35 | … d = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
| ~~~~~~~~~~~~~
| Exception calling "Parse" with "1" argument(s): "String '05/26/2021 08:31:03' was not recognized as a valid DateTime."
MethodInvocationException:
Line |
35 | … d = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
| ~~~~~~~~~~~~~
| Exception calling "Parse" with "1" argument(s): "String '12/18/2019 00:19:15' was not recognized as a valid DateTime."
MethodInvocationException:
Line |
35 | … d = '{0:dd}.{0:MM}.{0:yyyy}' -f [datetime]::parse("$($_.created_at)")
| ~~~~~~~~~~~~~
| Exception calling "Parse" with "1" argument(s): "String '06/22/2021 10:20:10' was not recognized as a valid DateTime."
Karen
Сообщения: 12
Зарегистрирован: 20 авг 2021, 10:34
Поблагодарили: 1 раз

Re: Ускорение сборки таблицы

Сообщение Karen »

Вот так работает:

Wake up, Neo, select all

$datecreated = Get-Date -Date $_.created_at -Format "dd.MM.yyyy"
Аватара пользователя
Fors1k
Администратор
Сообщения: 57
Зарегистрирован: 08 июн 2021, 17:23
Благодарил (а): 4 раза
Поблагодарили: 3 раза

Re: Ускорение сборки таблицы

Сообщение Fors1k »

Здорово)
Загляните в статью про работу с датой (Список команд > Дата и время), думаю вам будет интересно ;)
Там, кстати, это пятый пример.

Ответить

Кто сейчас на конференции

Сейчас этот форум просматривают: Marinadhu, maximllkn и 7 гостей