.NET 2006
Using the .NET Profiler API to Collect Object Instances for
Constraint Evaluation
Presented by:Dave Arnold
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006
Outline• Introduction to OCL 2.0• Relationship to UML and MDA• Problem / Solution• Compiling C# with OCL• OclAny::AllInstances()• The .NET Profiler API• Getting the information back to the application• Putting it all together• Issues / Conclusion• References
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 OCL 2.0
• OCL – Object Constraint Language
• Standardized by the OMG in August 2003
• Main use is for adding constraints to UML models
– Pre-Conditions
– Post-Conditions
– Class Invariants
• Can also be used to define derived attributes and methods (Queries)
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Relationship with UML
• UML diagrams alone do not contain enough information:
• The OCL can be used to specify additional information:
– context Customer::age : Integer
– init: 18
– context Customer inv:
– self.age > 17
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
-age : int
Customer
.NET 2006 Model Driven Architecture
• Importance of using models in the development process
• Consists of three main steps:
1. Construct a model at a high level of abstraction, free of all implementation technologies (PIM)
2. Transform the PIM model into one or more models that contain implementation details (PSM)
3. Transform the PSM to implementation code
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Model Driven Architecture
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
PIM
PSM PSM
CODE CODE
First Transformation First Transformation
SecondTransformation
.NET 2006 The Problem
• When a UML model is transformed into code what do we do with the OCL?
– Ignore it?
• Then why use it?
– Translate it into source code?
• How do we later determine what code was OCL and what was not?
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 A Solution
• Integrate the OCL directly into a high level language
• The OCL will be expressed separately from the language constructs
• Allows for enabling/disabling of the OCL and for extracting the OCL constraints from the code level back to the model
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Code Example
class Customer
{
OCL
[
"context Customer::age : Integer"
"init: 18"
]
private int age;
}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Why use C#?
• Multipurpose high level language
• Fully reflexive (round trip)
• Source code available for compilers
– SSCLI
– MONO
• .NET languages are compatible
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Compiling C# without OCL
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
LexicalAnalyser
ParserSemanticAnalyser
ErrorManager
CodeGenerator
SourceText Tokens AST
AugmentedAST
.NET 2006 Compiling C# and OCL
• Steps to add the OCL to the compilation process:
1. Construct an OCL parser
2. Implement the OCL class library in C#
3. Map each OCL construct to a corresponding C# construct (or code block)
4. Merge the OCL parse tree(s) with the C# parse tree and generate executable code
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Compiling C# and OCL
• The OCL lexical analyzer was written by hand
LexicalAnalyser
ParserSemanticAnalyser
ErrorManager
CodeGenerator
SourceText Tokens AST
AugmentedAST
LexicalAnalyser
SourceText Tokens
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Compiling C# and OCL
• The parser was constructed using a parser generator (JAY) from the OCL grammar
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
Lexical Analyser
ParserSemanticAnalyser
ErrorManager
CodeGenerator
SourceText Tokens AST
AugmentedAST
LexicalAnalyser
SourceText Tokens
Parser
AST
.NET 2006 Compiling C# and OCL
• During the C# semantic pass a reference model is created
• This reference model is used to perform the semantic pass on the OCL AST(s)
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
LexicalAnalyser
ParserSemanticAnalyser
ErrorManager
CodeGenerator
SourceText Tokens AST
AugmentedAST
LexicalAnalyser
SourceText Tokens
Parser
AST
ReferenceModel
SemanticAnalyser
AugmentedAST
.NET 2006 Compiling C# and OCL
• Once the OCL semantic pass is complete the result is merged into the C# augmented AST
• The resultant AST is then sent to the code generator to generate the executable code
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Compiling C# and OCL
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
LexicalAnalyser
ParserSemanticAnalyser
ErrorManager
CodeGenerator
SourceText Tokens AST
AugmentedAST
LexicalAnalyser
SourceText Tokens
Parser
AST
ReferenceModel
SemanticAnalyser
AugmentedAST
.NET 2006 OclAny::allInstances()
• One of the issues that was encountered during the implementation of our specialized compiler was OclAny::allInstances()
• The evaluation of the allInstances operation requires determining the set of all active object instances for a given classifier
• As our application is being executed via the .NET CLR it is non-trivial to obtain such a set
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Why is it non-trivial?
• The .NET CLR provides automated memory management for both allocation and garbage collection
• As memory management is abstracted away from the programmer, it is difficult to determine which object instances are allocated and active
• We have devised an approach for accessing memory management information from the CLR via the use of the .NET Profiler API
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 The big picture
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
C# Augmented With OCLC#/OCL Compiler
IL Code
Common Language Runtime
Garbage Collector
Memory
OCL Profiler
Gen
erat
es
Calls
Tra
cks
Manages
Notifies
Input
Run
s
.NET 2006 Enter the .NET Profiler API
• To obtain the set of live object instances we will need to get inside the CLR and look at the managed heaps
• The .NET Profiler API allows for an external COM component to monitor the execution and memory usage of an application running under the CLR
– Normally the profiler monitors the running application and does not interfere with it
– In our approach we will monitor object instance allocation and garbage collection and we will return this information to the managed application
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Implementing the Profiler
• The .NET Profiler API supports approximately sixty events
• We only need to specify behaviour for five of them
1. ICorProfilerCallback::Initialize()
2. ICorProfilerCallback::ObjectAllocated()
3. ICorProfilerCallback::MovedReferences()
4. ICorProfilerCallBack::ObjectReferences()
5. ICorProfilerCallback::RuntimeSuspendFinished()
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Initialize(IUnknown * pICorProfilerInfoUnk)
// Initialize - Sets up the profiler and registers for the CLR events that we want
HRESULT COCLProfilerCallback::Initialize(IUnknown * pICorProfilerInfoUnk)
{
// Get the ICorProfilerInfo interface we need, and stuff it away in a member variable.
HRESULT hr = pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo,
(LPVOID *)&m_pICorProfilerInfo);
if(FAILED(hr)) return E_INVALIDARG;
// Indicate which events we're interested in.
m_dwEventMask = 0;
m_dwEventMask += COR_PRF_MONITOR_SUSPENDS; // For GC notification
m_dwEventMask += COR_PRF_MONITOR_GC; // For all GC calls except ObjectAllocated
m_dwEventMask += COR_PRF_ENABLE_OBJECT_ALLOCATED; // For ObjectAllocated call
m_dwEventMask += COR_PRF_MONITOR_OBJECT_ALLOCATED; // For ObjectAllocated call
// Set the event mask
m_pICorProfilerInfo->SetEventMask(m_dwEventMask);
return S_OK;
}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 ObjectAllocated(UINT objectId, UINT classId)
• ObjectAllocated is invoked every time memory on the managed heap is allocated for a new object– The first parameter is a pointer to the managed heap
location where the object instance is being stored
– The second parameter is a pointer to the class descriptor
• The method stores the first parameter in an internal data structure so that the object instance can be found later– In order to reduce overhead, only classifiers which are
required are stored
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 MovedReferences(…)
• MovedReferences is invoked to notify the profiler that the garbage collector has moved one or more object instance locations– The parameters specify the new locations for the object
instances (pointers)
• The method simply updates the internal data structure to reflect the new locations
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 ObjectReferences(…)
• ObjectReferences is invoked once for each object instance that remains in the managed heap after a garbage collection operation
• When the method is called we will mark the corresponding object instance as active in our internal data structure
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 RuntimeSuspendFinished()
• RuntimeSuspendFinished is called once all of the execution threads have been suspended for a garbage collection operation
HRESULT COCLProfilerCallback::RuntimeSuspendFinished()
{
// Loop through each of the objects and mark them as collected
ObjectInstance* oi = m_objects.GetFirstItem();
while(oi != NULL)
{
oi->Collect();
oi = m_objects.GetNextItem();
}
return S_OK;
}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Getting the Information to the Managed Application
• The preceding five methods define a profiler that will keep track of which object instances are active at a given point in time
• The next step is getting this information to the managed application that is running
– This is accomplished by having the profiler export five methods that can be called from within the managed application
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Getting the Information to the Managed Application
// Determines if the OCL Profiler is attached to this instance of the CLR VM
[DllImport("OCLProfiler.dll")]
private static extern bool IsOCLProfilerAttached();
// Registers the given classifier type with the OCL Profiler so that we keep information
// about the classifier
[DllImport("OCLProfiler.dll", CharSet=CharSet.Unicode)]
private static extern void RegisterObject(string name);
// Gets the number of instances that have been allocated of the given classifier type
[DllImport("OCLProfiler.dll", CharSet=CharSet.Unicode)]
private static extern int GetInstanceCount(string name);
// Starts the instance copy operation. The instance copy operation is used to build the
// allInstances set
[DllImport("OCLProfiler.dll")]
private static extern void StartInstanceCopy();
// Stops the instance copy operation.
[DllImport("OCLProfiler.dll")]
private static extern void StopInstanceCopy();
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Getting the Information to the Managed Application
public static ArrayList GetInstancesFor(string value, Type t)
{
VerifyProfiler();
int count = GetInstanceCountFor(value);
ArrayList result = new ArrayList();
StartInstanceCopy();
for(int i =0;i<count;i++)
{
// Use the type information to create a new object
// The profiler will be informed of the new allocation
// and will copy the memory used by the existing object
// into our new object...thus creating an allInstances set
// that is a complete copy of each object instance
Object obj = t.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.CreateInstance, null, null, null);
result.Add(obj);
}
StopInstanceCopy();
return result;
}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Putting it all together
• We have integrated the previous method into our specialized C#/OCL compiler
Customer.allInstances()->forAll(c : Customer | c.age >= 18)
bool result = true;foreach(Customer c in (Set)OCLProfilerControl.GetInstancesFor(“Customer”, System.Type.GetType(“Customer”))) { result = result & (c.age >= 18);}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Putting it all together
OCL
[
"context AllInstances::Main() : OclVoid"
"post: Customer.allInstances()->forAll(
c : Customer | c.age >= 18)"
]
public static void Main()
{
Customer cs = new Customer();
cs.name = "Dave";
cs.age = 27;
Customer cs2 = new Customer();
cs2.name = "Mary";
cs2.age = 16;
}
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Putting it all together
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Issues
• Threading– Works in a single threaded model and uses
critical sections to prevent new object instances from being created during the copying process, etc.
• Speed
– The runtime profiler introduces significant overhead, thus reducing performance
– As the OCL constraints are designed to be used during development only this may not be an issue
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Conclusion
• The method presented here has been used to implement software based constraints via the OclAny::AllInstances operation– It would be interesting to explore other uses
for the complete set of live object instances
– We are currently exploring how our method can be used in the verification and validation of non-functional requirements
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006
.NET 2006 Acknowledgements & Additional Information
AcknowledgementsFunding for this work has been generously
provided by the Natural Sciences and Engineering Research Council of Canada
Additional Information + Source Codehttp://www.ewebsimplex.ca/csocl or email: [email protected]
Questions or Comments?
4th International Conference on .NET Technologies. University of West Bohemia, Plzen, Czech Republic. May 29 – June 2 nd 2006