以下Postで複数属性、複数タグへのBulkでの書き込み方法を紹介しました。

AFSDKによる複数属性、複数PIタグへのBulk書き込み

今回は複数アイテムのBulkでの読み込みをご紹介します。

なお、Bulkコールの他にParallelコールがあり、どちらが良いかはシチュエーションにより異なります。

以下KBを参考にしてください。(英語)

 

KB01216 - AF SDK Performance: Serial vs. Parallel vs. Bulk

https://techsupport.osisoft.com/Troubleshooting/KB/KB01216

 

BulkコールについてAFSDKのヘルプにサンプルコードがあります。

https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/abb5db84-4593-4937-b146-428622f719f2.htm

なお、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の方がコードは書きやすいかと思います。