@Chung: The memory is not freed up after the PI ACE Calculation completed. Let me describe the work flow (shown to Figure 1) to explain this principle.
When you register a PI ACE Calculation module for the first time, it writes configuration instructions to the PI ACE Scheduler (thereafter named the Scheduler) in the PI Module Database (PI MDB) and creates the first context to which it will apply. A context will apply to a PI Server for referring to one or many PI Points or to a PI Module including PI Aliases that are referencing PI Points. When a context is started using the PI ACE Manager (Step 1), it writes information to the PI MDB (Step 2), the PIACENetScheduler.exe process reads the PI MDB (Step 3) and passes ACE Context information (such as the .NET assembly file or .dll file containing your calculation) to the PIACEClassLibraryHost.exe process (Step 4). The PIACEClassLibraryHost.exe process instantiates an object from the MyCalculation1 Class contained in the MyCalculations.dll assembly (Step 5) which will define your calculation context 1. Each context will configure an Execution Queue that will be filled up by a timer (clock-based calculation) or by the PI Update Manager Subsystem. Every time values are put on the Execution Queue, the ACECalculations method from the MyCalculation1 Class is triggered. Whatever is declared at the class level will remain in memory until the Context 1 stops. 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.
The .NET Framework's garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap. As long as address space is available in the managed heap, the runtime continues to allocate space for new objects. However, memory is not infinite. Eventually the garbage collector must perform a collection in order to free some memory. The garbage collector's optimizing engine determines the best time to perform a collection, based upon the allocations being made. When the garbage collector (GC) performs a collection, it checks for objects in the managed heap that are no longer being used by the application and performs the necessary operations to reclaim their memory. You should destroy your unused objects or set them to a Null value (or Nothing in VB .NET) between the calculation calls.
In some special scenarios where you have to handle the creation of several thousands of PIACEPoint objects through loops, you might have to call a collection by the GC to free up the resources before the end of your process.
There are some elements to look first if you think you experience insufficient memory exception.
- If you have created a 32-bit PI ACE module, you will be limited by the use of 1.6 GB (near 2 GB) or RAM, a 64-bit PI ACE module will have as far as 2 TB for Windows Server 2008 R2 or 192 GB on Windows 7.
- If you have calculations with large numbers of contexts, you may want to distribute the contexts between two or more instances of the executable. Normally, all instances of a PI ACE class run in a single instance of the host. In PI ACE 2010 R2 and later, it will be possible to run multiple schedulers and divide contexts among them.
- To correct memory problems, begin by examining the calculations. Unused tags, calculations or contexts can all contribute to low-memory conditions. If you have a large number of executables, each with relatively few contexts, consider including more than one class in each executable.
To answer your second question, objects created within the ACECalculations method 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 class level variables and initialize them in the ModuleDependentInitialization method. You must be careful about objects out of scope, there are no immediately freed by the GC. The best way to free your resources faster is to call the Dispose method or assign a Null value before you leave the ACECalculations method.