以下Postで複数属性、複数タグへのBulkでの書き込み方法を紹介しました。
今回は複数アイテムのBulkでの読み込みをご紹介します。
なお、Bulkコールの他にParallelコールがあり、どちらが良いかはシチュエーションにより異なります。
以下KBを参考にしてください。(英語)
KB01216 - AF SDK Performance: Serial vs. Parallel vs. Bulk
https://techsupport.osisoft.com/Troubleshooting/KB/KB01216
BulkコールについてAFSDKのヘルプにサンプルコードがあります。
なお、listResultsに対してParallelで結果を取得することも可能です。(結果についてParallelを使用しているのでデータ取得はシングルのBulkコールです)
以下サンプルです。
PIServer myPIDataArchive = PIServer.FindPIServer("PIDataArchiveName");
// For tag search mask
String TagNameMask = "testtag*";
//Start Time and End Time
AFTimeRange timeRange = new AFTimeRange("*-10d", "*");
PIPointList pointList = new PIPointList(PIPoint.FindPIPoints(myPIDataArchive, TagNameMask));
int counter1 = 0;
PIPagingConfiguration config = new PIPagingConfiguration(PIPageType.TagCount, 100);
//Stopwatch Start
Stopwatch sw1 = Stopwatch.StartNew();
//Bulk Call for pointList
IEnumerable<AFValues> listResults = pointList.RecordedValues(timeRange, AFBoundaryType.Inside, "", true, config);
Parallel.ForEach(listResults, afValues =>
{
Console.WriteLine(afValues.PIPoint);
foreach (AFValue value in afValues)
{
counter1 += 1;
//Console.WriteLine(value.PIPoint + ":" + value.Timestamp.LocalTime + " : " + value.Value.ToString());
}
});
//Stopwatch Stop
sw1.Stop();
//Write results
Console.WriteLine("Bulk Call Results");
Console.WriteLine("Event number : " + counter1);
Console.WriteLine("Bulk Time : " + sw1.Elapsed.TotalSeconds);
Parallelを使用する場合、上記コードに付随して以下で使用できます。
//Parallel
int counter2 = 0;
//Stopwatch Start
Stopwatch sw2 = Stopwatch.StartNew();
//Parallel call for pointList
Parallel.ForEach(pointList, new ParallelOptions { MaxDegreeOfParallelism = 8 }, piPoint =>
{
var afValues = piPoint.RecordedValues(timeRange, AFBoundaryType.Interpolated, null, false);
Console.WriteLine(piPoint.Name);
foreach (AFValue value in afValues)
{
counter2 += 1;
//Console.WriteLine(value.PIPoint + ":" + value.Timestamp.LocalTime + " : " + value.Value.ToString());
}
});
//StopStopwatch
sw2.Stop();
//Write results
Console.WriteLine("Parallel Call Results");
Console.WriteLine("Event number : " + counter2);
Console.WriteLine("Parallel Time : " + sw2.Elapsed.TotalSeconds);
KBにも記載がありますが、複数アイテムを取得する場合、シングルスレッドでループすると遅くなってしまいます。
Parallelを使用する際は終了が同期されているわけではないので、アプリケーション側で同期などは対処する必要があり、コードが複雑になるケースがある点はご注意ください。
例えばファイル書き出しなどする場合、Parallel.ForEach内では複数アクセスになるため、書き出せません。
比較すると、Bulkの方がコードは書きやすいかと思います。