jyu_SI

Point Attribute retrieval

Discussion created by jyu_SI on Dec 6, 2013
Latest reply on Dec 10, 2013 by jyu_SI

Background:

 

On the PI Server, I have a set of point attributes unique to a custom point class. One of these attributes contains a unique ID string (or possibly a list of unique IDs) that match an individual PI Point to our own database servers.

 

I have a program using the PI SDK that lives between PI and our database servers. It takes event messages sent from our database servers and adds those events to a corresponding PIPoint. The message I receive only uses the aforementioned unique ID string to identify its source point.

 

In order to match up a source point to the PI Point, I need to search the PIPoints list for a matching ID contained in the point attributes. And if it doesn't exist, I need to create a new PI Point.

 

Problem:

 

I'm now handling a large number of points. This process now takes way too long. My current solution is to create a map of these IDs to PIPoints when my program starts up, but it's now resulting in a very long startup, reaching up to 20 minutes. (Once this process is complete, it is no longer performed, and the program runs smoothly. Occasionally, some changes need to be made to the PointAttribute values, but that is not a common event, and it does not significantly impact performance)

 

The method below handles one ID and matches it to a PIPoint. "piPoints" is a Server.PIPoints instance. "mapSrcIDToPIPoint" is a Dictionary <long, PIPoint> instance.

 

I have a similar method that just iterates through the entire PIPoints list and maps every single point to mapSrcIDToPIPoint. All IDs are guaranteed to be matched to only one point, however one point can have multiple IDs.

 

Using Stopwatch, retrieving the point class name and particularly the point attribute retrieval seem to be the most time consuming calls.

 

I have simplified some parts of this method to make it easier to read.

 
        private bool mapPIPoint(long inputSrcID)
        {
                string[] strArySourceID;
                foreach (PIPoint p in piPoints)
                {
                    if (p.PointClass.Name == MY_POINTCLASS_NAME)
                    {
                        // get SourceID PointAttribute
                        strArySourceID = ((string)p.PointAttributes[MyAttrConstants.PTATTR_ID].Value).Split(',');



                        // map ID to PIPoint
                        long piSrcID;
                        foreach (string s in strArySourceID)
                        {
                            if (Int64.TryParse(s, out piSrcID))
                            {
                                if (inputSrcID == piSrcID)
                                {
                                    if (mapSrcIDToPIPoint.ContainsKey(piSrcID))
                                        mapSrcIDToPIPoint[piSrcID] = p;
                                    else
                                        mapSrcIDToPIPoint.Add(piSrcID, p);
                                    return true;
                                }
                            }
                        }
                    }
                }
            // source ID does not exist in the PI Server
            return false;
        }

 Question:

 

I cannot change the format of the message I receive. So with that in mind, does anyone have ideas to make this process more efficient? I'm a relative newbie to C# and the PISDK so I could be missing something obvious that I'm unaware of.

Outcomes