I know that using Weakreference is not without cost, but about the cost, I have some questions.
@swgillespie do you want to take a shot at these?
@ygc369 did you try to measure it yourself? BenchmarkDotNet is pretty useful. Another option is to inspect the source code.
Or are you looking at best practices and guidance when to use WeakReference vs. GCHandle?
What is the cost? GC time, memory space, or both? GCHandle?
Weak references create an entry in the handle table. The handle table is quite efficient but allocating a huge amount of handles will degrade performance in general.
When the target of a weak reference dies, the GC must null out the weak reference. There is a cost to this that is proportional to the number of weak refs that died during a GC.
How much is the cost?
+1 for using BenchmarkDotNet for getting this information.
Why does Weakreference has extra cost while strong ref does not have? When GC, strong ref need to be updated too, why couldn't weak ref be updated the same way as strong ref?
Weak references must be nulled out when the target is collected, but they do not have to be marked through (weak references to not keep an object alive). Strong references do not need to be nulled out (because the target of a strong ref is not collected) but they must be marked through and updated upon GC relocation. There is overhead for each and each requires the GC to inspect the handle table multiple times throughout a GC.
Can I create a lot of objects and allocate a weakreference for each of them? For example, 100000 objects, acceptable or not?
There's nothing stopping you from doing this, but the performance will likely degrade with that many handles. How bad, I can't say without benchmarking.
If I allocate many weakreferences whose target is the same object, do they share some cost? Would the total cost be less than the one that each weakref has a different target?
No. Intuitively, each weak reference is a "weak pointer" to an object that doesn't keep the object alive. If the weak reference target dies, all weak references that point to the object must be nulled out.
No. Intuitively, each weak reference is a "weak pointer" to an object that doesn't keep the object alive. If the weak reference target dies, all weak references that point to the object must be nulled out.
Why not let all weak references that have same target share one entry in the handle table?
That's a good question. Can you think about which operations would be more expensive, which operations would be cheaper and which operations would be impossible if we have done that; and whether it would be a good tradeoff for most .NET programs out there?
@ygc369 In some recent work on Roslyn, there were a large number of weak references getting cleaned up. They did not form a meaningful amount of time for the performance issue I was diagnosing. This is not to say they are without cost, but simply to say that work has been done to make them efficient enough to use them where they provide the right functionality for some task. See dotnet/roslyn#19493.
@swgillespie
@jkotas
@sharwell
What data structure is the handle table? An array or a link list? If it is an array, it has to be reallocated when we create more weak references than its capacity. Does this matter?
Another question, can an object "know" whether it has been weak referenced without searching the handle table?
@jkotas
If you find it hard to make a tradeoff, why not to provide both mechanisms and let users decide which to use according to their use case? It would be fine to provide another form of weak ref which shares same entry for same target.
@ygc369 we appreciate your curiosity, but I would like to ask you to try to do a bit research before asking questions / suggesting features.
We are more than happy to help community members to learn more, especially when they are stuck or the code is above their understanding, but we do not scale to answer lots of questions about code details which can be answered by poking at code, testing it on your own, etc. If we tried to answer all such questions, we would not have time to do anything else, which, as you can probably understand, is not desirable.
As such I would like to ask you to look at the code, spend some time reading it (hours/days, depending on complexity of the code), using BenchmarkDotNet to test performance if you are interested. If you get stuck after deeper investigations, we will be happy to point you in the right direction. Is that fair?
Thanks for understanding!
There is also gitter chat room for CoreFX and CoreCLR which you can use for discussions with other contributors who might be interested in similar topic.
@karelz
I tried to look at source code, but found that much of "core" code seems not opened. I see code from http://referencesource.microsoft.com/, and find that many C# classes (including WeakReference) use "extern" C++ function, but I can't see C++ implement code.
@ygc369 Here you go:
I tried to look at source code, but found that much of "core" code seems not opened.
@ygc369 <shameless plug> I wrote a blog post that might help you find your way round the CoreCLR source, see A Hitchhikers Guide to the CoreCLR Source Code </shameless plug>
Thanks @mattwarren - I was about to ping you to provide some insights :).
@ygc369 Matt is great example of someone who does lots of research on CoreCLR/CoreFX source code. - see all his blog posts, or Twitter account. It is actually joy for us to help contributors as Matt, who write about our source code, and when he has questions, we are happy to answer them and help him.
It seems you entirely missed the fact the source code is here on GitHub, in CoreFX and CoreCLR repos. I would suggest you to read our README.md files in both repos. Potentially also in CoreRT repo. It will likely answer lots of your questions. We also have extensive documentation in all repos, so I would suggest you to browse through the Documentation directories.
Thanks!
Closing for now.
Most helpful comment
@ygc369 we appreciate your curiosity, but I would like to ask you to try to do a bit research before asking questions / suggesting features.
We are more than happy to help community members to learn more, especially when they are stuck or the code is above their understanding, but we do not scale to answer lots of questions about code details which can be answered by poking at code, testing it on your own, etc. If we tried to answer all such questions, we would not have time to do anything else, which, as you can probably understand, is not desirable.
As such I would like to ask you to look at the code, spend some time reading it (hours/days, depending on complexity of the code), using BenchmarkDotNet to test performance if you are interested. If you get stuck after deeper investigations, we will be happy to point you in the right direction. Is that fair?
Thanks for understanding!
There is also gitter chat room for CoreFX and CoreCLR which you can use for discussions with other contributors who might be interested in similar topic.