-
Improvement
-
Resolution: Unresolved
-
Medium
-
None
-
None
-
None
I've noticed this for a while and wanted to document this performance issue.
When calling this free function:
points::appendAttribute(...)
This calls down into the following chain for every leaf node:
PointDataLeafNode<T, Log2Dim>::appendAttribute() AttributeSet::appendAttribute() AttributeArray::create()
There are two mutexes here that significantly affect performance:
- AttributeArray::create() has a file scope mutex that lives in AttributeArray.cc and is locked on accessing the registry in a singleton pattern (the registry is stored as a static variable).
- There is a second mutex that lives in the registry itself to ensure concurrent access and registering of attribute types is thread-safe.
What I'd like to propose is a way to lock the second of these mutexes just once when calling points::appendAttribute() and then subsequently call a chain of "unsafe" methods that don't require mutex locking. This implicitly locks the first. This could perhaps only be used in the very common case of appending a uniform attribute (ie when creation is very fast).
I think the best way to handle this might be to create a tbb::scoped_lock from the calling class and then pass it to a new static method with an implementation that lives in AttributeArray.cc that does something like this:
void AttributeArray::acquireRegistryLock(tbb::scoped_lock& lock) { LockedAttributeRegistry* registry = getAttributeRegistry(); lock.acquire(registry->mMutex); }
That way the mutex and registry aren't actually exposed and the lock will release it when it goes out of scope. Any thoughts on that?