tech.guitarrapc.cóm

Technical updates

PowerShellで任意の個数毎にObjectを取り出す (こっちがホント

たいがー道場...というのは冗談で、前回の記事Select-Objectを用いて任意の個数ごとにObjectを取り出す例の別解です。 前回のは 二重ループ ( Select-Objectはそれ自体でループしている) だったので、今回は別方法を利用します。 こっちは、パフォーマンス上の低下が回避されています。

Foreach-Objectでいってみよう

ぱっと思いつくのはこれですね。
$Items = ps
$GroupNum = 20
[ScriptBlock]$ScriptBlock = {(Get-Date).DateTime}
$Items | %{$i=1}{$_; if($i % $GroupNum -eq 0){&$ScriptBlock};++$i}
これで、Get-Process (ps) の20個毎に、Get-Dateでその時刻が出ます。
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
	142      11     1876       2960    89             432 atieclxx
	100       6      800        996    25             840 atiesrxx
	110       9     8404       7580    38    41.81   5736 audiodg
	146      15     2880       1576    76            1492 BingDesktopUpdater
	117      11     2060       1588    61            1752 c2c_service
	832      94    82304       5304   879    18.45   4412 CCC
	 30       4      576        368    27            5228 conhost
	277      19     8896       2948   408     0.05   6936 CSISYN~1
	446      14     2460       1980    68             436 csrss
	465      28     2792      11648   243             536 csrss
	347      19     9688      14548    86            1116 dasHost
	 88       7     1672       3176    34            6364 dllhost
	241      29    55080      35420   304             976 dwm
	103       9    21200      20324   117    20.00   4708 Everything-1.2.1.421b
   1752     837    82168      86520   946   119.57   3560 explorer
	138      12     2808       8056   105     0.03   7388 FlashUtil_ActiveX
   1035      68   161720      82960   518 2,046.06   6736 GOM
   2085      88   142320      23400   625    57.21   1908 holLaunchPadOnline
	  0       0        0         20     0               0 Idle
	162      17     3728       3268   101     1.98   4596 IDM
2013年6月13日 5:36:14
   1224     306   255600     338020   757    94.71   4796 iexplore
	743      71    45424      74752   329    10.62   8288 iexplore
	601      39    10184      31664   174     4.23   8444 iexplore
	176      13    12396      17752   199     5.60   3616 ImeBroker
	203      16     7172       2612   110            1568 IpOverUsbSvc
	366      20     4248       3320    95     0.62    800 jusched
	292      21     4384       2704   111     0.73   4052 KHALMNPR
	917      99   177316     237256   913   227.01   7632 krile
	351      18    19132       2436   173    10.65   1100 lightscreen
   1169      27    10732      12288    62             628 lsass
	274      35     7576       6864   188    52.78   4516 MagicFormation
	493      55    41672       9484   716     7.71   5012 mmc
	295      34    27212       4356   586     0.34   5024 MOM
	494      84   114240      97344   280            2016 MsMpEng
	588      63   472556     268884   740 1,982.21   6264 opera
	 73       7     1040        920    66     0.12   6952 pageant
	544      75   164580     205256  1324   277.00   4788 powershell_ise
	167      26    26364       2292   514            3668 PresentationFontCache
	240      25    22524      16548   211    27.49   3536 RaUI
	103       8     1712       6616    73     0.02   9088 RuntimeBroker
2013年6月13日 5:36:14
	606      55    30892      10144   661            4076 SearchIndexer
	279      11     7316       7828    36             612 services
	253      21     6164       2400   133    10.72   1080 SetPoint
	639      44    11992       9376   145     4.13   3272 SkyDrive
	607      40    65504      34376   222   426.87   4108 Skype
	 36       2      292        508     5             316 smss
	365      20     3864       3156    73            1328 spoolsv
	373      43   204328      12356   298            1640 sqlservr
	 79       9     1428       1336    43            1852 sqlwriter
   1090      45    41432      27688   146             372 svchost
	393      15     4560       5940    45             732 svchost
	527      16     7536       7912    44             772 svchost
	842      32    21580      18964   127             884 svchost
   2021      81   240268     213240   550             912 svchost
	854      42    16016      20292   119             988 svchost
	942      86    19592      15088  1542            1152 svchost
	473      41    24716      19672   400            1356 svchost
	 96      10     3364       1332    42            1472 svchost
	519      29    10972      14892    94            1688 svchost
	137      11     2324       2616    44            1896 svchost
2013年6月13日 5:36:15
	137      14     3728       1596    46            1996 svchost
	399      32    10716      11440   960            4260 svchost
	949       0      136        540    11               4 System
	321     342     9764      14512   665     4.10   3592 taskhostex
	 96      10     1388       1684    48            1936 vmnat
	 50       7     1116       1328    27            2056 vmnetdhcp
	254      17     6872       3252    97            2324 vmware-authd
	148      12     2136       2160    71            2124 vmware-usbarbitrator64
	 74       8      940        696    54             528 wininit
	149       8     1728       2052    70             588 winlogon
	150      14     5628      15004   117     0.44   4360 WinSCP
	118      10     1808       2260    42            5204 wlanext
	103       8     1956       1496    32            9652 WmiPrvSE
	447      26     8860       8816   103            4384 wmpnetwk
	211      10     1456       1232    43            3008 WUDFHost
	203       9     1420       1480    43            4840 WUDFHost
	292      26    13760      26044   164     0.28   3880 WWAHost
	 78       7     1144       1200    67     0.02   1200 ZuneLauncher

Foreachでいってみよう

以前のベンチマークでもわかる通り、PowerShellのForeach-Objectは便利ですがパフォーマンスがトテモ悪いです。 そのため、PowerShellにおいてもう少しましなforeachでやってみましょう。
$Items = ps
$GroupNum = 20
[ScriptBlock]$ScriptBlock = {(get-date).DateTime}

$i=1
foreach($item in $items)
{
	$item; if($i % $GroupNum -eq 0){&$ScriptBlock};++$i
}

Foreach-ObjectとForeachでそんなに違うの?

簡単なベンチで。 Foreach-Objectです。
$Items = 1..100000
$GroupNum = 20
[ScriptBlock]$ScriptBlock = {(get-date).DateTime}
Measure-Command{
	$Items | %{$i=1}{$_; if($i % $GroupNum -eq 0){&$ScriptBlock};++$i}
}
Foreachです。
$Items = 1..100000
$GroupNum = 20
[ScriptBlock]$ScriptBlock = {(get-date).DateTime}

Measure-Command{
	$i=1
	foreach($item in $items)
	{
		$item; if($i % $GroupNum -eq 0){&$ScriptBlock};++$i
	}
}
結果です。 Foreach-Object : TotalMilliseconds : 6659.746 Foreach : TotalMilliseconds : 3639.2884 ねみゅいのでfunctionはいいや