YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

Optimizing requests to PI Server Options · View
nfcae
#1 Posted : Monday, August 23, 2010 10:57:36 AM
Rank: Member
Groups: Member

Joined: 8/23/2010
Posts: 12
Location: Portugal, Lisbon
Hello Smile ,

I stumbled upon a problem related to the number of access to the pi server using PI SDK (to optimize reports performance) and I've been trying this for a number of days with no success. What I'm trying to do is something like this (C#):

DataTable GetTagsInterpulatedValues(List<string> tagsToFetchData, List<Period> periods, string filterExp)

What I'm trying to do is with each tag from "tagsToFetchData" retrieve for example 3 periods (dateStart and dateEnd) and with a PI Equation filter Round, of course this isn't very hard to do if i do a foreach for each tag and use another foreach for the periods and apply the filter to the tags PI Data but this makes multiple accesses to the PI server.. what i wanted to do is make all this 1 request.. is there any way to do this? Notice that the filter must have the tagname to make the round filter.. is there any more general way to apply to all tags?

Thanks in advance,
Phil




Sponsor  
 

OSIsoft vCampus is a subscription-based, online offering that consists of providing everything people need to develop applications on the PI System.
We invite you to take a "tour" of the OSIsoft Virtual Campus - also feel free to consult the FAQ  or contact OSIsoft vCampus for more details.
RJK Solutions
#2 Posted : Monday, August 23, 2010 12:12:46 PM
Rank: Administration

Groups: Administration

Joined: 6/20/2008
Posts: 612
Location: Cheshire, United Kingdom.
Hi Phil,

Welcome to the forum.

To minimise round trips to a PI server you could use a PointList object but the only data methods implemented in the latest PISDK is ArcValue. So if you have a list of tags and want the snapshot value or an archived value at a time, then a PointList will only make 1 call to the PI server. However, if you want Summary type data then you have to make individual calls on each PIPoint object - I believe OSIsoft are going to address this at some point in the future.

Another optimising technique is to make use of the multi-threaded PI server by making asynchronous PISDK calls instead of synchronous. In some cases there has been 10 times performance improvement but really depends on what you are doing.

Don't suppose you could post a bit more of your code to see what is going on...
Principal Consultant
Real-Time Data Management @ Wipro Technologies
nfcae
#3 Posted : Monday, August 23, 2010 12:53:20 PM
Rank: Member
Groups: Member

Joined: 8/23/2010
Posts: 12
Location: Portugal, Lisbon
Thanks for the fast response Smile, I'll post the entire method i got so far and an example how i would use it.

Example Code:

List<string> tagsToFetchData = new List<string>();
tagsToFetchData.Add("SUBSTN.ANGLE1");
tagsToFetchData.Add("SUBSTN.ANGLE2");

List<Period> periods = new List<Period>();
periods.Add(new Period(new DateTime(2010, 1, 1), new DateTime(2010, 1, 2))); //Analyse Data from 1 january 2010 to 2 january 2010
periods.Add(new Period(new DateTime(2010, 1, 5), new DateTime(2010, 1, 6))); //Also Analyse from 5 january 2010 to 6 january 2010

//the following is wrong but you'll understand my problem here..I'm trying to round the values but also i want the values that aren't questionable also for all tags
string filterExp = "Round([ALL_TAGS], 22.5) AND IsSet([ALL_TAGS], \"q\") = 0"

public DataTable GetTagsInterpulatedValues(List<string> tagsToFetchData, List<Period> periods, string filterExp)
{
DataTable dt = new DataTable();
DataColumn timestamp = new DataColumn("timestamp", Type.GetType("System.String"));
dt.Columns.Add(timestamp);

PointList points = new PointList();

foreach (string tag in tagsToFetchData) {
PIPoint point = piServer.PIPoints[tag];
points.Add(point);

DataColumn dc = new DataColumn(tag, Type.GetType("System.String"));
dt.Columns.Add(dc);
}

ListData points_data = points.Data;
NamedValues trash;
foreach(Period p in periods) {
PointValueLists period_vals = points_data.InterpolatedValues(p.iniPeriod, p.endPeriod, 0, filterExp, FilteredViewConstants.fvRemoveFiltered, out trash, null);
foreach (PointValueList lst in period_vals)
{
PIValues pointValues = lst.PIValues;
}
}
return dt;
}

I know It's rather complicated, if its not possible could you suggest anything i could optimize here?

Quote:
Another optimising technique is to make use of the multi-threaded PI server by making asynchronous PISDK calls instead of synchronous. In some cases there has been 10 times performance improvement but really depends on what you are doing.


I find this interesting, is there any documentation i could see or an example how to achieve this?

Again thanks for your help Smile

**EDIT** i forgot to assign the results to the DataTable but you get the main idea of what I'm trying to do d'oh!
RJK Solutions
#4 Posted : Monday, August 23, 2010 1:45:27 PM
Rank: Administration

Groups: Administration

Joined: 6/20/2008
Posts: 612
Location: Cheshire, United Kingdom.
I will get back to the details of your post shortly, but have you considered using the PI-OLEDB provider? It seems that the manner in which you want the results could simply be the result of a SQL query via the PI-OLEDB provider. Ultimately PI-OLEDB calls are translated to PISDK calls but it may reduce your applications code footprint/complexity.

I will get you an asynchronous example once I have a few mintues spare (not sure I ever have spare time BigGrin)
Principal Consultant
Real-Time Data Management @ Wipro Technologies
nfcae
#5 Posted : Monday, August 23, 2010 2:01:40 PM
Rank: Member
Groups: Member

Joined: 8/23/2010
Posts: 12
Location: Portugal, Lisbon

Quote:
I will get back to the details of your post shortly, but have you considered using the PI-OLEDB provider? It seems that the manner in which you want the results could simply be the result of a SQL query via the PI-OLEDB provider. Ultimately PI-OLEDB calls are translated to PISDK calls but it may reduce your applications code footprint/complexity.


We are actually converting an already made PI OLEDB query to this method here (we are talking of millions of data to be processed here that was the reason of changing Tongue).

Maybe I'll end up to separate them for each different filter if its not possible to combine filters in only 1 expression.

Thanks again!
Phil

**EDIT** I've tried using the methods from ListData using PointsList and it seems they aren't implemented (NotImplementedException): Summary, InterpolatedValues.. the only one that you mentioned works but that method only retrieves one element (ArcValue). Seems like they are still working on this class leaving me to the threaded execution you mentioned.
RJK Solutions
#6 Posted : Tuesday, August 24, 2010 8:32:45 PM
Rank: Administration

Groups: Administration

Joined: 6/20/2008
Posts: 612
Location: Cheshire, United Kingdom.
Here is a quick example to get you going on using asynchronous calls on a pointlist object:

Code:

        Dim _PISDK As New PISDK.PISDK()
        Dim _PointList As New PISDK.PointList()

        _PointList.Add(_PISDK.Servers.DefaultServer.PIPoints("sinusoid"))

        Dim _PIValue(_PointList.Count - 1) As PISDK.PIValue
        Dim _PIAsynchStatus(_PointList.Count - 1) As PISDKCommon.PIAsynchStatus

        For i As Integer = 0 To _PointList.Count - 1
            _PIAsynchStatus(i) = New PISDKCommon.PIAsynchStatus
            Try
                _PIValue(i) = _PointList.Item(i + 1).Data.Summary("*-1d", "*", PISDK.ArchiveSummaryTypeConstants.astAverage, PISDK.CalculationBasisConstants.cbEventWeighted, _PIAsynchStatus(i))
            Catch ex As Exception
                MsgBox(String.Format("Index {0} has error of {1}.", i, ex.Message))
            End Try
            If (i = _PointList.Count - 1) Then
                For j As Integer = 0 To _PointList.Count - 1
                    Do
                    Loop While _PIAsynchStatus(j).ProgressPercent < 100
                Next
            End If
        Next

        For i As Integer = 0 To _PointList.Count - 1
            MsgBox(_PIValue(i).Value)
        Next


Obviously you need to optimise it (including error handling) to your own particular needs.

Hope this helps.
Principal Consultant
Real-Time Data Management @ Wipro Technologies
nfcae
#7 Posted : Wednesday, August 25, 2010 5:29:43 PM
Rank: Member
Groups: Member

Joined: 8/23/2010
Posts: 12
Location: Portugal, Lisbon
Thanks for the code, I'm going to analyse it now Smile
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.