// We should see nothing here
Module 9: Memory and Resource Management |
41 |
|
|
|
//NOTE: If the object referred to by wr doesn't have a
//Finalize code,
//then wr would think that the object is dead regardless of
//whether wr is tracking resurrection or not.
//The following line attempts to create a strong reference
//to the object.
obj = (BaseObj) wr.Target;
Display("Strong reference to object obtained: " + (obj != null));
if (obj != null) {
//The strong reference was obtained so this wr must be
//tracking resurrection. At this point we have a strong
//reference to an object that has been finalized but its
//memory has not yet been reclaimed by the collector. obj.Display("See, I'm still alive");
//Destroy the strong reference to the object obj = null;
//Collect reclaims the object's memory since this
//object has no Finalize code registered for it
//anymore.
Collect();
WaitForFinalizers();
obj = (BaseObj) wr.Target; // This now returns null Display("Strong reference to object obtained: " + (obj != null));
}
//Cleanup everything about this demo so there is no effect
//on the next demo
//Destroy strong reference (if it exists)
obj = null;
wr = null; // Destroy the WeakReference object (optional) Collect();
WaitForFinalizers();
//NOTE: You are discouraged from using the
//WeakReference.IsAlive property
//because the object may be killed immediately after
//IsAlive returns making the return value incorrect.
//If the Target property returns a non-null value,
//then the object is alive and will stay alive
//since you have a reference to it. If Target returns null,
//then the object is dead.
Display(-1, String.Format(
"Demo stop: WeakReferences that {0}track resurrections.", trackResurrection ? "" : "do not "), 0);
}
42 Module 9: Memory and Resource Management
Topic Objective
To explain how the .NET Framework common language runtime uses a system of generations to make garbage collection more efficient.
Lead-in
To improve the performance of garbage collection, the
.NET Framework uses a system based on object generations.
!To Force Garbage Collection of Generation 0 Through a Specified Generation:
void System.GC.Collect(int Generation); void System.GC.Collect(int Generation);
! To Determine the Generation of an Object:
Int32 System.GC.GetGeneration(Object obj); Int32 System.GC.GetGeneration(Object obj);
!To Return the Maximum Number of Generations That the System Currently Supports:
Int32 System.GC.MaxGeneration;
Int32 System.GC.MaxGeneration;
*****************************ILLEGAL FOR NON-TRAINER USE******************************
To improve the performance of garbage collection, the .NET Framework uses a system based on object generations, which works as follows:
1.When a managed object is created by using the new operator and is added to the managed heap, it becomes part of generation 0.
2.After garbage collection is invoked, any generation 0 objects that remain in the managed heap are promoted to become members of generation 1.
3.Any generation 1 objects that remain in the managed heap are promoted to become members of generation 2.
Because generation 2 is the highest generation that is currently supported, generation 2 objects that remain in the managed heap remain in generation 2.
When garbage collection is invoked to free heap space, its performance is improved because it only compacts the section of the managed heap that contains generation 0 objects.
Typically, the newer an object is, the shorter its lifetime will be. Therefore, sufficient space is usually freed when generation 0 is compacted. If sufficient space cannot be obtained when generation 0 is compacted, garbage collection will compact the older generations.
Module 9: Memory and Resource Management |
43 |
|
|
|
To force the collection of generations from 0 through a specified generation, you can call the .NET Framework System.GC.Collect method, as follows:
void System.GC.Collect(int Generation);
The System.GC.GetGeneration method returns the current generation of an object as follows:
Int32 System.GC.GetGeneration(Object obj);
The System.GC.MaxGeneration property returns the maximum number of generations that the system currently supports. It is written as follows:
Int32 System.GC.MaxGeneration;
// Displays 1
// Displays 0
44 Module 9: Memory and Resource Management
Demonstration: Generations
Topic Objective
To demonstrate how garbage collection handles generations.
Lead-in
This demonstration shows how garbage collection handles generations.
*****************************ILLEGAL FOR NON-TRAINER USE******************************
For Your Information
Use the debugger to step through the code while you point out features and ask students what they think will happen next. In this section run the GenerationDemo method.
This demonstration shows how garbage collection handles generations.
//This method demonstrates how objects are promoted between
//generations.
//Applications could take advantage of this info to improve
//performance but most applications will ignore this info. private static void GenerationDemo() {
Display(0, "\n\nDemo start: Understanding Generations.", +1);
//Let's see how many generations the managed heap supports
//(we know it's 2)
Display("Maximum GC generations: " + GC.MaxGeneration);
//Create a new BaseObj in the heap GenObj obj = new GenObj("Generation");
//Since this object is newly created, it should be in
//generation 0
obj.DisplayGeneration();
// Performing a GC promotes the object's generation Collect();
obj.DisplayGeneration();
Collect(); |
|
|
|
obj.DisplayGeneration(); |
// Displays |
2 |
|
Collect(); |
|
|
|
obj.DisplayGeneration(); |
// Displays |
2 |
(max generation) |
(Code continued on the following page.)
// We should see nothing
|
Module 9: Memory and Resource Management |
45 |
// Destroy the strong reference to |
this object |
|
|
obj = null; |
|
|
|
|
Collect(0); |
// Collect |
objects in generation 0 |
|
|
WaitForFinalizers(); |
// We should see nothing |
|
|
// Collect objects in generations 0 and 1 Collect(1);
WaitForFinalizers();
Collect(2); |
// Same as |
Collect() |
// Now, we should see the Finalize |
code run |
WaitForFinalizers(); |
|
|
Display(-1, "Demo stop: Understanding Generations.", 0);
}
46 Module 9: Memory and Resource Management
Additional Performance Features
|
|
|
|
Topic Objective |
|
|
|
To introduce additional |
|
|
|
resources for improved |
|
! Performance Monitoring |
|
application performance. |
|
|
|
|
|
Lead-in |
|
! Large Object Heap |
|
In addition to |
|
! Multiprocessor Support |
|
programmatically |
|
|
manipulating garbage |
|
! Unsafe Code |
|
collection through weak |
|
|
references and generations, |
|
|
|
you can use other features |
|
|
|
and techniques to improve |
|
|
|
application performance. |
|
|
|
|
|
|
|
|
|
|
|
*****************************ILLEGAL FOR NON-TRAINER USE******************************
In addition to programmatically manipulating garbage collection through weak references and generations, you can use other features and techniques to improve application performance.
Performance Monitoring
You can obtain real-time information about the memory activity of the .NET
Framework common language runtime by using performance counters.
You can view these counters by using the Performance Monitor tool (Perfmon.exe). To execute this program, click Start, click Run, and in the text box, type perfmon.exe.
You can also execute the program by clicking Control Panel, double-clicking
Administrative Tools, and double-clicking Performance.
To view .NET Framework common language runtime memory statistics in the
Performance window:
1.Click the System Monitor icon under the Console Root folder.
2.Click the + button in the right pane to add a counter to the System Monitor.
3.Specify the computer that you wish to monitor.
4.In the Performance object field, select .NET CLR Memory.
5.Select the desired counters and application instance.
You can obtain descriptions of the counters by clicking the Explain button.
In the future, you will also be able to read these counters by using the APIs that will be provided by the .NET Framework class library.
Module 9: Memory and Resource Management |
47 |
|
|
|
Large Object Heap
Objects that are larger than 20,000 bytes are allocated from a separate special heap. Garbage collection handles large objects in the same way as it handles other managed heap objects, except it does not compact the separate special heap to avoid the additional performance cost of shifting large blocks of memory.
Multiprocessor Support
The .NET Framework common language runtime provides two forms of garbage collection: a server version (MSCorSvr.dll) and a workstation version (MSCorWks.dll). The server version is multithreaded and highly scalable, while the workstation version is single-threaded and concurrent. Both versions feature low fragmentation, low overhead, and efficient use of cache space.
The server version of the common language runtime contains features that improve the efficiency of resource collection. With synchronization-free allocations and scalable collections, a multiprocessor system receives a managed heap that is split into as many sections as there are CPUs. Each CPU has its own thread, which enables the runtime to perform garbage collection on different heaps simultaneously. If you have a garbage collection bottleneck, you can improve performance by scaling your application to a multiprocessor system.
Using Unmanaged Code to Control Garbage Collection
When you need a higher degree of control or that extra margin of performance, C# provides the ability to write code that can deal directly with pointer types, and fix objects to temporarily prevent garbage collection from moving them. You must clearly mark such code in C# with the unsafe modifier. This ensures that other developers cannot possibly use unsafe features accidentally, and that the compiler and the common language runtime work together to ensure that unmanaged code cannot masquerade as safe code.
You should note that unmanaged code is not verifiable by the .NET Framework common language runtime and should only be executed when trusted. It does, however, offer developers and users a way to optimize performance.
Further discussion of unmanaged code and memory management is beyond the scope of this course.
48 Module 9: Memory and Resource Management
Lab 9: Memory and Resource Management
Topic Objective
To introduce the lab.
Lead-in
In this lab, you will learn how to use classes to create an application that explicitly manages resources by implementing a design pattern that is based on the IDisposable interface. You will also learn how to create an application that implicitly manages resources by using destructors.
*****************************ILLEGAL FOR NON-TRAINER USE******************************
Objectives
After completing this lab, you will be able to:
!Create an application, with classes, that explicitly manages resources by implementing a design pattern based on the IDisposable interface.
!Create an application that implicitly manages resources by using destructors.
Lab Setup
Starter and solution files are associated with this lab. The starter files are in the folder <install folder>\Labs\Lab09\Starter. The solution files for this lab are in the folder <install folder>\Labs\Lab09\Solution.
Scenario
In this lab, you are provided with a Microsoft Visual Studio® .NET console application as a starting point. The application is named Memory and Resource Management. It allows a user to enter text data. When the user has finished entering data, the application outputs the number of completed sentences and the character count, and then the text. The text is formatted so that each sentence is displayed on a separate line without an ending period.
The application is implemented by using a SentenceFormatter object that buffers the input text until a completed sentence is detected or until its Close method is called.
Module 9: Memory and Resource Management |
49 |
|
|
|
When a completed sentence is detected or its Close method is called, the
SentenceFormatter object sends its buffered text to a SimpleTextBuffer object. The SimpleTextBuffer object buffers this text until it is closed or finalized. At that time, the SimpleTextBuffer object outputs its buffered text to the console.
In this lab, the Memory and Resource Management application is used to illustrate some key points about .NET Framework resource management. To provide explicit and implicit resource management, you will modify this program to follow the design pattern that is described in Module 9.
Estimated time to complete this lab: 60 minutes
50 Module 9: Memory and Resource Management
Exercise 1
Programming for Explicit Resource Management
In this exercise, you will modify the Memory and Resource Management application to incorporate explicit resource management.
!Examine the application
1.In Visual Studio .NET, open the Memory and Resource Management project, which is located in <install folder>\Labs\Lab09\Starter\ Memory and Resource Management.
2.Open the Memory and Resource Management.cs file and examine the code.
3.Build and run the Memory and Resource Management application. The following text should appear in the console output:
Enter text, when finished enter an empty line
4. Enter the following text, which is followed by an empty line, as prompted: hello world.are you out there?
Text similar to the following should appear in the console output:
SimpleTextBuffer:
hello world
are you out there?
Completed Sentences 1, Output Characters 29
hit enter to exit program