1 Reply Latest reply on May 19, 2016 3:23 PM by bshang

    What is the fastest way to get a static attribute value from multiple Elements

    p.clemme

      Hi there

      I writing a custom datareference making timeseries based on eventframes.

      The dataference is rolling up a result on multiple child element.

      As part of the dataference I need to get a static attribute value from each of the child element

      I would have thought that getting the eventframes would be the slowest part, but it actually turns out to be getting the static values.

      I have tried many ways to get the attribute values, but cannot seem to get to perform.

       

      Is there a fast way to get a static attribute value from multiple elements fast?

       

      I have added some stopwatches to my code to see the performance of difference parts of the code.

       

      The last method using attributeTemplate, elements and LoadElement, seems to be the fastest, but I was wondering if there is a faster way to get all the attributes from the elements.

      1.5 second for finding the instantiated attributes of a type in a single query is pretty slow.

      The elements are all based on the same template.

       

      Using  find elementAttributes

      TOC Get Attributes: 00:00:01.4334836

      TOC Get Attribute Values: 00:00:00.0131367

      TOC Create Dict: 00:00:00.0005128

       

      public static Dictionary<string, DateTime> ElementTocDictionaryFind(AFDatabase afDatabase, string elementName, string elementCategory, string attributeName)

       

      var stopWatch = new Stopwatch();

       

      var elementTocDictionary = new Dictionary<string, DateTime>();

       

      //Get all elements

       

      var afAttributes = new AFAttributeList();

       

      var elementTemplate = afDatabase.ElementTemplates["WtgBaseTemplate"];

       

      var splitAttributeName = attributeName.Split('|');

       

      var lastAttributeName = splitAttributeName[splitAttributeName.Length-1];

       

      var category = afDatabase.ElementCategories[elementCategory];

       

      AFAttribute.FindElementAttributes(afDatabase, null, elementName, category, elementTemplate, AFElementType.Any, lastAttributeName, null,

       

      TypeCode.DateTime, true, AFSortField.ID, AFSortOrder.Ascending, Int32.MaxValue);

       

      Debug.WriteLine(string.Format("TOC Get Attributes: {0}", stopWatch.Elapsed));

       

      AFValues values = afAttributes.GetValue();

       

      Debug.WriteLine(string.Format("TOC Get Attribute Values: {0}", stopWatch.Elapsed));

       

      for (int i = 0; i < afAttributes.Count; i++)

       

      Convert.ToDateTime(values[i].Value);

       

      Debug.WriteLine(string.Format("TOC Create Dict: {0}", stopWatch.Elapsed));

       

      return elementTocDictionary;

       

       

      using findelements

      TOC Get Elements: 00:00:00.2474593

      TOC Load Attributes: 00:00:00.2793046

      TOC Get Attributes: 00:00:00.0043015

      TOC Get Attribute Values: 00:00:00.0132460

      TOC Create Dict: 00:00:00.0000945

       

      public static Dictionary<string, DateTime> ElementTocDictionaryElementTemplate(AFDatabase afDatabase, string elementName, string elementCategory, string attributeName)

       

      var stopWatch = new Stopwatch();

       

      var elementTocDictionary = new Dictionary<string, DateTime>();

       

      //Get all elements

       

      var elements = Util.GetElements(afDatabase, null, elementCategory, elementName);

       

      Debug.WriteLine(string.Format("TOC Get Elements: {0}", stopWatch.Elapsed));

       

      AFAttributeTemplate attributeTemplate = null;

       

      var elementTemplate = afDatabase.ElementTemplates["WtgBaseTemplate"];

       

      List<AFAttributeTemplate> loadTemplateList = new List<AFAttributeTemplate> { attributeTemplate };

       

      AFElement.LoadAttributes(elements, loadTemplateList);

       

      Debug.WriteLine(string.Format("TOC Load Attributes: {0}", stopWatch.Elapsed));

       

      var afAttributes = new AFAttributeList();

       

      foreach (var afElement in elements)

       

      var attribute = afElement.Attributes[attributeName];

       

      Debug.WriteLine(string.Format("TOC Get Attributes: {0}", stopWatch.Elapsed));

       

      AFValues values = afAttributes.GetValue();

       

      Debug.WriteLine(string.Format("TOC Get Attribute Values: {0}", stopWatch.Elapsed));

       

      for (int i = 0; i < afAttributes.Count; i++)

       

      Convert.ToDateTime(values[i].Value);

       

      Debug.WriteLine(string.Format("TOC Create Dict: {0}", stopWatch.Elapsed));

       

      return elementTocDictionary;

       

       

       

        • Re: What is the fastest way to get a static attribute value from multiple Elements
          bshang

          How many elements are returned? How many elements are in the AF Database? Do you restart the SQL server after each test? If not, the second one is likely hitting the SQL cache and will be faster.

           

          Assuming approach 2 with FindElements is via a "cold start", then ~0.5 sec latency is fairly normal.

           

          If you'd like more granularity, you can use an AFProbe class here: AFProbe

           

          Usage is simply:

           

          using ("name of measurement", _piSystemReference)

          {

          // AF SDK call

          }

           

          and it will write to the Console, but you can change the class to write to another output stream.

           

          You can refer to Exercise 2 here for a walkthrough.

          Advanced-Programming-With-PI-AF-SDK-TechCon2016/Advanced-Programming-with-PI-AF-SDK-Workbook.pdf

           

          With that being said, the above may not tell us too much in terms of how to optimize. Approach 2 above is already using the recommended pattern for partial loading.

           

          If we can see what is Util.GetElements (i.e. the actual FindElements AF SDK call) it may be helpful but I'm assuming you're not doing anything out of the ordinary with that call.

           

          Note we are improving the search implementation starting from AF 2.8 and plan to support improved attribute searches in the future, so we do try to improve the performance. Some of the (hidden) cost here may be due to "forced" sorting in prior versions that can be avoided in 2.8 when the client doesn't not require it (e.g. many non-UI applications, custom rollup DR). For small numbers of elements, it likely won't matter, but if you plan to scale this out, then it likely will.

          1 of 1 people found this helpful