Destroy target of WeakReference - c#

I'm writing a small MemoryManager for my WPF application and reached the following problem.
What i do: I store a lot of instances as a WeakReference in a IList<WeakReference>. Later, when i want to free all memory, i want to destroy all alive objects in the list.
To do this, i try to get the reference to the object, like this:
foreach (WeakReference wr in references)
{
if (wr.IsAlive == true)
{
if(wr.Target != null)
{
TypedReference tf = __makeref(wr.Target);
}
}
}
But i dont't know how to destroy tf. I tried to use __refval, but it does not work for me.
Sample:
InstanceDestructManager idm = new InstanceDestructManager();
IList<string> test = new List<string>();
test.Add("123");
idm.AddNullable<IList<string>>(ref test);
idm.Dispose();
// Should not be possible, because after idm.Dispose "test" should be null
test.Add("456");
General code for:
public static void Test(ref object pa)
{
pa = null;
}
Maybe some one has an idea, thank you!

Setting the WeakReference.Target to null will release the reference to it. There is no such thing as destroy memory in C#. The GC collect memory when there are no references to it. And even then it decides on its own when to free them. GC.Collect forces this. But this is not for production purposes unless you know what you're doing.

Related

Chance of hitting the same function at the same time by two Threads/Tasks

Assuming the following case:
public HashTable map = new HashTable();
public void Cache(String fileName) {
if (!map.ContainsKey(fileName))
{
map.Add(fileName, new Object());
_Cache(fileName);
}
}
}
private void _Cache(String fileName) {
lock (map[fileName])
{
if (File Already Cached)
return;
else {
cache file
}
}
}
When having the following consumers:
Task.Run(()=> {
Cache("A");
});
Task.Run(()=> {
Cache("A");
});
Would it be possible in any ways that the Cache method would throw a Duplicate key exception meaning that both tasks would hit the map.add method and try to add the same key??
Edit:
Would using the following data structure solve this concurrency problem?
public class HashMap<Key, Value>
{
private HashSet<Key> Keys = new HashSet<Key>();
private List<Value> Values = new List<Value>();
public int Count => Keys.Count;
public Boolean Add(Key key, Value value) {
int oldCount = Keys.Count;
Keys.Add(key);
if (oldCount != Keys.Count) {
Values.Add(value);
return true;
}
return false;
}
}
Yes, of course it would be possible. Consider the following fragment:
if (!map.ContainsKey(fileName))
{
map.Add(fileName, new Object());
Thread 1 may execute if (!map.ContainsKey(fileName)) and find that the map does not contain the key, so it will proceed to add it, but before it gets the chance to add it, Thread 2 may also execute if (!map.ContainsKey(fileName)), at which point it will also find that the map does not contain the key, so it will also proceed to add it. Of course, that will fail.
EDIT (after clarifications)
So, the problem seems to be how to keep the main map locked for as little as possible, and how to prevent cached objects from being initialized twice.
This is a complex problem, so I cannot give you a ready-to-run answer that will work, (especially since I do not currently even have a C# development environment handy,) but generally speaking, I think that you should proceed as follows:
Fully guard your map with lock().
Keep your map locked as little as possible; when an object is not found to be in the map, add an empty object to the map and exit the lock immediately. This will ensure that this map will not become a point of contention for all requests coming in to the web server.
After the check-if-present-and-add-if-not fragment, you are holding an object which is guaranteed to be in the map. However, this object may and may not be initialized at this point. That's fine. We will take care of that next.
Repeat the lock-and-check idiom, this time with the cached object: every single incoming request interested in that specific object will need to lock it, check whether it is initialized, and if not, initialize it. Of course, only the first request will suffer the penalty of initialization. Also, any requests that arrive before the object has been fully initialized will have to wait on their lock until the object is initialized. But that's all very fine, that's exactly what you want.

memory management impact on setting objects to null in finally

public void func1()
{
object obj= null;
try
{
obj=new object();
}
finally
{
obj = null;
}
}
is there any advantage of assigning null to a reference in finally block in regards of memory management of large objects?
Let's deal with the explicit and implicit questions here.
Q: First and foremost, is there a point in assigning null to a local variable when you're done with it?
A: No, none at all. When compiled with optimizations and not running under a debugger, the JITter knows the segment of the code where a variable is in use and will automatically stop considering it a root when you've passed that segment. In other words, if you assign something to a variable, and then at some point never again read from it, it may be collected even if you don't explicitly set it to null.
So your example can safely be written as:
public void func1()
{
object obj = new object();
// implied more code here
}
If no code in the "implied more code here" ever accesses the obj variable, it is no longer considered a root.
Note that this changes if running in a non-optimized assembly, or if you hook up a debugger to the process. In that case the scope of variables is artificially extended until the end of their scope to make it easier to debug.
Q: Secondly, what about fields in the surrounding class?
A: Here it can definitely make a difference.
If the object surrounding your method is kept alive for an extended period of time, and the need for the contents of a field has gone, then yes, setting the field to null will make the old object it referenced eligible for collection.
So this code might have merit:
public class SomeClass
{
private object obj;
public void func1()
{
try
{
obj=new object();
// implied more code here
}
finally
{
obj = null;
}
}
}
But then, why are you doing it like this? You should instead strive to write cleaner code that doesn't rely on surrounding state. In the above code you should instead refactor the "implied more code here" to be passed in the object to use, and remove the global field.
Obviously, if you can't do that, then yes, setting the field to null as soon as its object reference is no longer needed is a good idea.
Fun experiment, if you run the below code in LINQPad with optimizations on, what do you expect the output to be?
void Main()
{
var s = new Scary();
s.Test();
}
public class Scary
{
public Scary()
{
Console.WriteLine(".ctor");
}
~Scary()
{
Console.WriteLine("finalizer");
}
public void Test()
{
Console.WriteLine("starting test");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("ending test");
}
}
Answer (mouseover to show when you think you've got it):
.ctor
starting test
finalizer
ending test
Explanation:
Since the implicit this parameter to an instance method is never used inside the method, the object surrounding the method is collected, even if the method is currently running.

Memory leak when ThreadLocal<T> is used in cyclic graph

I just came across this weird 'behavior' of the Garbage Collector concerning System.Threading.ThreadLocal<T> that I can't explain. In normal circumstances, ThreadLocal<T> instances will be garbage collected when they go out of scope, even if they aren't disposed properly, except in the situation where they are part of a cyclic object graph.
The following example demonstrates the problem:
public class Program
{
public class B { public A A; }
public class A { public ThreadLocal<B> LocalB; }
private static List<WeakReference> references = new List<WeakReference>();
static void Main(string[] args) {
for (var i = 0; i < 1000; i++)
CreateGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
// Expecting to print 0, but it prints 1000
Console.WriteLine(references.Count(c => c.IsAlive));
}
static void CreateGraph() {
var a = new A { LocalB = new ThreadLocal<B>() };
a.LocalB.Value = new B { A = a };
references.Add(new WeakReference(a));
// If either one of the following lines is uncommented, the cyclic
// graph is broken, and the programs output will become 0.
// a.LocalB = null;
// a.LocalB.Value = null;
// a.LocalB.Value.A = null;
// a.LocalB.Dispose();
}
}
Although not calling Dispose is not good practice, but it's the CLR's design to clean up resources (by calling the finalizer) eventually, even if Dispose is not called.
Why does ThreadLocal behave differently in this regard and can cause memory leaks when not disposed properly in case of a cyclic graph? Is this by design? And if so, where is this documented? Or is this a bug in the CLR's GC?
(Tested under .NET 4.5).
Microsoft's David Kean confirmed that this actually is a bug.
The reason is that you're not calling Dispose. The garbage collector will only clean up objects that have finalizers as a last resort.

C# Lazy execution + memory understandings

Can you please explain to me what happens in the memory while executing the following code:
Case 1:
public static void Execute()
{
foreach(var text in DownloadTexts())
{
Console.WriteLine(text);
}
}
public static IEnumerable<string> DownloadTexts()
{
foreach(var url in _urls)
{
using (var webClient = new WebClient())
{
yield return webClient.DownloadText(url);
}
}
}
Let's assume after the first iteration I get html1.
When will html1 be cleared from the memory ?
on the next iteration?
when the foreach ends?
when the function ends ?
Thanks
** Edit **
Case 2:
public static void Execute()
{
var values = DownloadTexts();
foreach(var text in values)
{
Console.WriteLine(text);
}
}
public static IEnumerable<string> DownloadTexts()
{
foreach(var url in _urls)
{
using (var webClient = new WebClient())
{
yield return webClient.DownloadText(url);
}
}
}
To my understanding, Case 1 is better for the memory then case 2 right?
In case 2 will still keep a reference to the texts we already downloaded while in Case 1 every text is marked for garbage collection once its not used. Am I correct?
_urls will stay indefinitely because it is located in a field as it seems.
DownloadTexts() (the iterator returned by it) is kept alive until the end of the loop.
the WebClient and the html it produces stay alive for one iteration. If you want to know the absolute precise lifetime of it, you need to use Reflector and mentally simulate where the reference travels around. You'll find that the IEnumerator used in the loop references it until the next iteration has begun.
All objects that are not alive can be GC'ed. This happens whenever the GC thinks that is a good idea.
Regarding your Edit: The cases are equivalent. If you don't put the enumerator into a variable, the compiler will do that for you. It has to keep a reference till the end of the loop. It does not matter how many references there are. There is at least one.
Actually, the loop only requires the enumerator to be kept alive. The additional variable you added will also keep the enumerable alive. On the other hand you are not using the variable so the GC does not keep it alive.
You can test this easily:
//allocate 1TB of memory:
var items =
Enumerable.Range(0, 1024 * 1024 * 1024)
.Select(x => new string('x', 1024));
foreach (var _ in items) { } //constant memory usage
It will be cleared from memory when the garbage collector runs and determines that it's no longer in use.
The value will no longer be in use at the moment when the foreach causes the IEnumerator.MoveNext() method to be invoked. So, effectively, #1.
It will be cleared from memory when Garbage Collector will feel like doing so.
But starting point is when code holds no more references to instance of object.
So the answer in this case is: sometime after block in which you created object ends.
Have trust in GC, it is good at doing its job.

How can I write a unit test to determine whether an object can be garbage collected?

In relation to my previous question, I need to check whether a component that will be instantiated by Castle Windsor, can be garbage collected after my code has finished using it. I have tried the suggestion in the answers from the previous question, but it does not seem to work as expected, at least for my code. So I would like to write a unit test that tests whether a specific object instance can be garbage collected after some of my code has run.
Is that possible to do in a reliable way ?
EDIT
I currently have the following test based on Paul Stovell's answer, which succeeds:
[TestMethod]
public void ReleaseTest()
{
WindsorContainer container = new WindsorContainer();
container.Kernel.ReleasePolicy = new NoTrackingReleasePolicy();
container.AddComponentWithLifestyle<ReleaseTester>(LifestyleType.Transient);
Assert.AreEqual(0, ReleaseTester.refCount);
var weakRef = new WeakReference(container.Resolve<ReleaseTester>());
Assert.AreEqual(1, ReleaseTester.refCount);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.AreEqual(0, ReleaseTester.refCount, "Component not released");
}
private class ReleaseTester
{
public static int refCount = 0;
public ReleaseTester()
{
refCount++;
}
~ReleaseTester()
{
refCount--;
}
}
Am I right assuming that, based on the test above, I can conclude that Windsor will not leak memory when using the NoTrackingReleasePolicy ?
This is what I normally do:
[Test]
public void MyTest()
{
WeakReference reference;
new Action(() =>
{
var service = new Service();
// Do things with service that might cause a memory leak...
reference = new WeakReference(service, true);
})();
// Service should have gone out of scope about now,
// so the garbage collector can clean it up
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsNull(reference.Target);
}
NB: There are very, very few times where you should call GC.Collect() in a production application. But testing for leaks is one example of where it's appropriate.
Perhaps you could hold a WeakReference to it and then check to see that it no longer alive (i.e., !IsAlive) after the tests have completed.
Based on Paul's answer, I created a more reusable Assert method. Since string's are copied by value I added an explicit check for them. They can be collected by the garbage collector.
public static void IsGarbageCollected<TObject>( ref TObject #object )
where TObject : class
{
Action<TObject> emptyAction = o => { };
IsGarbageCollected( ref #object, emptyAction );
}
public static void IsGarbageCollected<TObject>(
ref TObject #object,
Action<TObject> useObject )
where TObject : class
{
if ( typeof( TObject ) == typeof( string ) )
{
// Strings are copied by value, and don't leak anyhow.
return;
}
int generation = GC.GetGeneration( #object );
useObject( #object );
WeakReference reference = new WeakReference( #object, true );
#object = null;
// The object should have gone out of scope about now,
// so the garbage collector can clean it up.
GC.Collect( generation, GCCollectionMode.Forced );
GC.WaitForPendingFinalizers();
Assert.IsNull( reference.Target );
}
The following unit tests show the function is working in some common scenarios.
[TestMethod]
public void IsGarbageCollectedTest()
{
// Empty object without any references which are held.
object empty = new object();
AssertHelper.IsGarbageCollected( ref empty );
// Strings are copied by value, but are collectable!
string #string = "";
AssertHelper.IsGarbageCollected( ref #string );
// Keep reference around.
object hookedEvent = new object();
#pragma warning disable 168
object referenceCopy = hookedEvent;
#pragma warning restore 168
AssertHelper.ThrowsException<AssertFailedException>(
() => AssertHelper.IsGarbageCollected( ref hookedEvent ) );
GC.KeepAlive( referenceCopy );
// Still attached as event.
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber( publisher );
AssertHelper.ThrowsException<AssertFailedException>(
() => AssertHelper.IsGarbageCollected( ref subscriber ) );
GC.KeepAlive( publisher );
}
Due to differences when using the Release configuration (I assume compiler optimizations), some of these unit tests would fail if GC.KeepAlive() were not to be called.
Complete source code (including some of the helper methods used) can be found in my library.
Use dotMemory Unit framework (it's free)
[TestMethod]
public void ReleaseTest()
{
// arrange
WindsorContainer container = new WindsorContainer();
container.Kernel.ReleasePolicy = new NoTrackingReleasePolicy();
container.AddComponentWithLifestyle<ReleaseTester>(LifestyleType.Transient);
var target = container.Resolve<ReleaseTester>()
// act
target = null;
// assert
dotMemory.Check(memory =>
Assert.AreEqual(
0,
memory.GetObjects(where => where.Type.Is<ReleaseTester>().ObjectsCount,
"Component not released");
}
This is not an answer, however you may want to try running your code in both Debug and Release modes (for comparison sake).
In my experience the Debug version of JIT'ed code is made easier to debug and thus may see references stay alive longer (I belive function scope) However, code JITed in Release mode may have the objects ready for collection quickly once it is out of scope and if a Collection happens.
Also not answering your question: :-)
I would be interested in seeing you debug this code using Visual Studio in Interop mode (Managed and Native) and then breaking after displaying a message box or something. Then you can open the Debug->Windows-Immediate and then type
load sos
(Change to thread 0)
!dso
!do <object>
!gcroot <object> (and look for any roots)
(or you can use Windbg as other's have posted in previous posts)
Thanks,
Aaron

Categories