My user-classes get instantiated the wrong number of times on each vertex.
-
Friday, July 15, 2011 8:35 PM
A customer bumped into an issue where a user-function tries to take a shared lock, but the lock was not being mutually exclusive as expected. The relevant code is shown below. However, what may happen is that multiple instances of MyClass are created and each has a separate lock. So what is going on?
1. Notice that the call to MyFunc() is a call to an instance method that implicitly references the this object.
2. when an instance is referred to in a query, the HpcLinq query compilers captures the instance and serializes it into a bag called HpcLinqObjectStore which is sent as side-information with the vertex code and the query plan.
3. The object is reincarnated in each vertex via calls to HpcLinqObjectStore.Get(int objectID).
=> it turns out that in Beta1/Beta2, HpcLinqObjectStore.Get uses a cache but does not guarantee that each process will get exactly one shared instance for each objectID. In general, we don't know what was intended, perhaps you want a common object but perhaps you want a fresh reincarnation every time.
=> To avoid problems, only reference immutable data of captured instances. For mutable things, instantiate object explicitly or use static data which is more obviously AppDomain-wide.
Problem code:
public class MyClass {
private object _lock = new Object();
public RunQuery(){
...
data.Select(rec => MyFunc(rec))
}
public MyFunc(){
lock(_lock){
..
}
}
}
Problem code summary:
data.Select(rec => this.Func(rec)) // where Func mutates something on this.
Better code #1 (instantiate fresh instances every time):
data.Select(rec=> new MyClass().Func(rec)); // every call to Func will be on a fresh instance of MyClass.
Better code #2 (use shared appDomain-wide data):
data.Select(rec=> StaticFunc(rec)); //StaticFunc can reference shared static vars.
All Replies
-
Friday, July 15, 2011 8:35 PM
(answer inline with question)- Marked As Answer by Mike Liddell, MSFT Friday, July 15, 2011 8:35 PM

