10 Replies Latest reply on Jul 26, 2010 8:11 PM by cjrancur

    Module level variables in ACE 2.0

    cjrancur

      I'd like to open a general discussion about module level variables in ACE 2.0.  I am particularly interested in impact on CPU usage, and how to avoid garbage collection that may put module level variables out of context.

       

      Here's my starting point.  The PI ACE user manual for ACE 1.2.32 and 2.1.32 gives an example on page 139 showing that module level variables should be used when possible to avoid allocating and instantiating variables over and over again within a subroutine.  The example given uses the vb6 "set" command syntax, so it seems clear to me that the example was written in the context of vb6 programming.

       

      I'm not sure that the same CPU optimization technique can be applied successfully for ACE 2.1.32 using vb.net, because I wonder if garbage collection will eventually cause the module level variables to go out of context.  Then the ACE program would need to catch the exception and revive the missing module level value.

       

      It would be nice if ACE does some "behind the scenes" work to protect any module level variables from garbage collection.  Can anyone tell me if that happens?  If I use module level variables to save CPU processing in ACE 2.1.32, how should I deal with possible garbage collection issues that may cause these module level variables to go out of context?  Have appropriate protections for module level variables, such as setting a variable to static or using a property function, been already built into ACE behind the scenes?  Or do I need to build that type of protective code explicitly?

        • Re: Module level variables in ACE 2.0
          michaelh

          Carrie Rancuret

          It would be nice if ACE does some "behind the scenes" work to protect any module level variables from garbage collection.  Can anyone tell me if that happens? 

           

          That was my understanding all the time. The ACENetScheduler should have instances of your modules (one per context) and keep them alive until taken "out of process" . Isn't this sufficient to inhibit garbage collection?
          If not, I were really interested in more background information on "ACE behind the scenes" and garbage collection. 

            • Re: Module level variables in ACE 2.0
              cjrancur

              Michael Hesselbach

              The ACENetScheduler should have instances of your modules (one per context) and keep them alive until taken "out of process" . Isn't this sufficient to inhibit garbage collection?

               

              I think that you and I are asking the same question, are ACE class level variables for each module maintained in the managed heap and do they always and necessarily survive garbage collection, given that the ACENetScheduler should keep instances of the modules alive?

               

              I know that there are times that ACE routines stop doing anything, although the ACENetScheduler shows the contexts are "on", and at the time these occur I have not been able to find an error in pimsglog, even though I write try/catch blocks about all subroutine code within ACE and write to the pimsglog if exceptions occur.  Restarting the ACE process, not just the context, is sometimes necessary to revive the non-responsive routines when this has happened to me in the past. It seems to happen at random, maybe at intervals of a couple weeks to a few months. The mystery of these events has led me to wonder, but not to be certain, about garbage collection in this context.

               

              I did some searching, and found a conceptual description of garbage collection here:

               

              http://www.codeproject.com/KB/dotnet/garbagecollection.aspx

               

              Then I found that .net framework 4 is beginning to provide some tools for discovering what objects remain and what are discarded after garbage collection, see the following links from msdn.  The newer tools include a profiling API for tracking moved references, which would be the references that are kept after a garbage collection round.  Also, there's a new event tracker in .net framework 4 that tracks additional statistics about garbage collection.  Doing the full analysis to answer our common question is beyond my resources.  Maybe someone at OSIsoft can take this on and provide a definitive answer.

               

              http://msdn.microsoft.com/en-us/library/bb384618.aspx

               

              http://msdn.microsoft.com/en-us/library/ff356162.aspx

               

              http://msdn.microsoft.com/en-us/library/ee851764.aspx

               

              http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx

               

               

                • Re: Module level variables in ACE 2.0

                  Carrie Rancuret

                  Michael Hesselbach

                  The ACENetScheduler should have instances of your modules (one per context) and keep them alive until taken "out of process" . Isn't this sufficient to inhibit garbage collection?
                  I think that you and I are asking the same question, are ACE class level variables for each module maintained in the managed heap and do they always and necessarily survive garbage collection, given that the ACENetScheduler should keep instances of the modules alive?
                  That’s exactly correct. As Michael already pointed out, when the host process "starts" a context, it basically instantiates an instance of the ACE module class, which remains in memory until the context is "stopped". All module level variables (defined as member variables for the module class) would also remain in memory for this duration, and are not subject to garbage collection.

                   

                  However, any local variables defined in the ACECalculations() routine would go out of scope, once the calculation corresponding to one execution time is completed. It is for this reason that the example described in PI ACE Manual (available on the vCampus Library, under vCampus PI Products Kit > Server Products) suggests that if one desires to repeatedly use certain variables, it is best to declare them as module-level variables and initialize them in the ModuleDependentInitialization() routine.

                    • Re: Module level variables in ACE 2.0
                      cjrancur

                      Thanks Steve, for the verification that ACE keeps module level variables alive throughout all scheduled runs of each module. 

                      • Re: Module level variables in ACE 2.0
                        cjrancur

                        I am testing some changes based on your recommendation.  For instance, I had some statements like "private x= new type" at the class module level in ACE.  I changed these to declare there, but to instantiate with "new" in the ModuleDependentInitialization routine.

                         

                        Here's one I wonder about.  I had this set up at module level:

                        Private Const dtmZero = #12/31/1969 6:00:00 PM#

                        How should I do that one?  I don't want it to be changed within the program, so I declared it a constant to prevent myself from messing with it if I forget my intent when making later program revisions in a few months or years.  But I have to put the value at the class level if it is a constant, and if I declare the constant within the ModuleDependentInitialization routine, is it available to all subroutines in the module class?

                          • Re: Module level variables in ACE 2.0
                            nagarwal

                            Hello Carrie,

                             

                            Here is some more clarification about this. The Wizard generated code basically defines a Class which inherits from the base class (PIACENetClassModule). When a context is started, an object of the type defined by this class definition is instantiated. Following its creation (in addition to other initialization stuff) the ModuleDependentInitialization() method is called. This implies that if you initialize any module level variables on the same line as declaration, these would be initialized when the class object is created. If you choose to initialize them in the ModuleDependentInitialization() method, these would be initialized whenever this method is called. Since both of these would be before you actaully use these variables in your calculations, it really doesn't matter which way you go - perhaps putting all initialization logic in the ModuleDependentInitialization() routine would be good coding practice. As for the const, its perfectly all right to set it during declaration at the class level. Please note that you can not declare any class level variables from the  ModuleDependentInitialization() routine, as anything declared here will be local and would go out of scope once this method exits.

                             

                            As previously mentioned, all module level variables would be in scope for the lifetime of the class module object (which is basically for as long as the context is running), and would not be subject to garbage collection. I hope this clarifies and I have not managed to confuse you further :).

                             

                            Regards,

                             

                            Nitin

                              • Re: Module level variables in ACE 2.0
                                cjrancur

                                Thanks a million, Nitan, that helped me understand ACE better.

                                 

                                Here's a scenario that I've had on an ACE routine that sometimes just stops providing the expected output, even though the ACENETScheduler says its running and the scheduler processor is on.  If I stop the ACE module, then it will start providing data again on restart.

                                 

                                This particular ACE executable also had an additional module in it.  Some module level variables declared as "friend" for the added module, and used also within the ACE class module. 

                                 

                                Would that conceivably cause ACE to stop providing outputs from an SDK and OLEDB based program, even though the ACENetScheduler might think the routine is running, and show it as "on"?  Would ACE prevent the friend module variables from going out of scope?

                                 

                                I thought maybe the separate module variables would cause trouble, so just in case, I consolidated all declarations, functions, and subroutines into the single ACE class module.  I probably will not know for weeks or months whether that helped or not, however, because the problem occurs only rarely.

                                 

                                Thanks again,

                                 

                                Carrie

                                 

                                 

                                  • Re: Module level variables in ACE 2.0
                                    nagarwal

                                    Hello Carrie:

                                     

                                    I am not sure if I understand the scenario completely. When you say this particular ACE Executable also had an additional module in it - are you referring to a new ACE module that you may have added to this executable (for e.g. by selecting "New" calculation in PIACEWizard) or a new VB module that you added to your Visual Basic project (for e.g. by using Add->Module in Visual Studio)? Assuming that it is the later, i.e. you added a new VB module to this project and declared some "Friend" functions and variables in this VB Module, I don't see any reason for the variables declared in this module to go out of scope. Basically, all variables declared in a standard VB module are global and exist for the life of the program.

                                     

                                    From what you have described so far, I find it hard to imagine a scenario where the ACE context may stop writing to the output tags because of garbage collection. Also, as Steve already pointed out - there could be lots of reasons for this problem and it is important to understand as to what is the exact state of the context when you run into the problem. For example, is it only that the output tags are not getting updated, while the calculations are still being scheduled and executed (you can tell this by looking at the ACE message log - provided correct log level is selected) or is it that the calculations are not even scheduled. You should also enable performance counters to detect any skipped calculations because of any loading issues. All these questions require more detailed investigation, and I would recommend you open a support call with our TechSupport - so we can look at this in detail. 

                                     

                                    Regards,

                                     

                                    Nitin 

                                      • Re: Module level variables in ACE 2.0
                                        cjrancur

                                        Thanks Nitin,

                                         

                                        A co-worker has been working with TechSupport to resolve this issue from the system side.  He said that OSIsoft mentioned there were resource issues on the ACE server to be addressed. Today, he moved ACE to a higher powered server under OSIsoft tech support direction.  He takes care of server system issues, and I take care of ACE application coding.  I was approaching this on vCampus to see if there was something I could do also to help with this problem on the Application side.  I went ahead last Friday and removed the VB module (added using Add->Module in Visual Studio) to rule out the separate VB module as a possible cause of this difficult to locate, intermittent issue.  It's nice to know that you don't believe that would be an issue, since I may use added VB modules again in the future for ACE exe's with lengthier code.

                                         

                                        Carrie

                              • Re: Module level variables in ACE 2.0

                                Carrie Rancuret

                                I know that there are times that ACE routines stop doing anything, although the ACENetScheduler shows the contexts are "on"
                                There could be lots of reasons and this would require more careful investigation. For example, is it a loading issue, are events still added to the execution queue, etc.? I suggest you open a ticket with our regular technical support to figure this out.