Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Improving containment list performance in CDO/EMF
Improving containment list performance in CDO/EMF [message #1846992] Mon, 11 October 2021 14:19 Go to next message
Alain Picard is currently offline Alain PicardFriend
Messages: 266
Registered: July 2009
Senior Member
Hi,

We are seeing some scalability issues with regards to ConcurrentAccessException when dealing with multi-valued containment references.

The scenario is essentially that the same container essentially contains most of the key new elements that are being added at a point in time. For example, a container for weekly orders containing all orders for a week. During that week, adding new orders will always add to the same container and create a "choke" point with that reference list.

The problem that we are observing, is that EMF translates a list add, which is an append operation, into an indexed add at the location of the size at the time of the add. This can quickly lead to ConcurrentAccessException in an environment like CDO where the index was computed as x and after another element was added, it will fail since the index should now be x+1.

What we would like to implement (and share back to EMF/CDO after), is the ability to do add that are real append, i.e. just append the element to the end of the list, whatever location that is. From what I can see, those adds would probably have to return the final insertion index back so that EMF can add those to notifications. On the CDO side there is still some transaction concurrency to address for sure.

What are your ideas? concerns ? etc.

Cheers,
Alain

On
Re: Improving containment list performance in CDO/EMF [message #1846996 is a reply to message #1846992] Mon, 11 October 2021 17:54 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Alain

I think you may be confusing some issues.

EMF is not threadsafe, so your concern about x changing to x+1 seems like an outright application bug; the addition should have been atomicized by the calling code..

EMF's use of ELIst for all collections is unfortunate, but provided collections are not too large the effort to use a Set doesn't pay off. However if you regularly have more than 100 siblings, I would consider ways to introduce some hierarchy, such as lists of lists or a custom data type that might support some genuine Map functionality.

I'm not clear why you are having problems with containment. Single containment is a fundamental property of both UML and Ecore. It only goes wrong when you allow child stealing to occur, which is either poor modelling or poor programming.

My experience is that the only major functionality, rather than performance, problem is [1]; duplicate references in non-containment for which I have to tweak the generated code.

Regards

Ed Willink

[1] https://bugs.eclipse.org/bugs/show_bug.cgi?id=89325
Re: Improving containment list performance in CDO/EMF [message #1846999 is a reply to message #1846996] Mon, 11 October 2021 18:18 Go to previous messageGo to next message
Alain Picard is currently offline Alain PicardFriend
Messages: 266
Registered: July 2009
Senior Member
Ed,

Thanks for the reply. I guess I might have failed to express myself correctly.

I know that EMF is not thread safe and in an RCP application context that was mostly a non-issue, but can be more challenging at times in supporting a web application.

But here I am referring to the concurrent access exception that will occur when 2 transactions are trying to add to the same containment at the same time. Each transaction local view of the containment list will have say 1200 items. Each transaction, through EList add/addUnique will ask to add the new element at index 1200. One will go through and the one that had to wait in line will fail since CDO will report (correctly I might add) that we're attempting to modify an historical version. The list now has 1201 elements and the attempt by the 2nd transaction to add at 1200 is now stale.

The goal here would be to match the semantic of add in list, which is to append. Then the 2nd transaction could go through without a rollback and re-processing of the transaction (granted transaction logic will have to be added on the CDO side to identify those cases and handle the historical modification and still proceed.

Hopefully this makes my case clearer.

Alain
Re: Improving containment list performance in CDO/EMF [message #1847006 is a reply to message #1846999] Mon, 11 October 2021 20:00 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Ok. But that sounds like a bug in that the second queued transaction should queue an add/append that remains valid after the first competes, rather than an insertAt that is invalidated. Sorry I'm not a CDO expert so cannot comment as to who got the transaction queue wrong. But even if the insertAt might be dubious positionwise, it should still be able to insert at a stale position unless the new position has evolved to beyond the end of the list. Bottom line, the ConcurrentAccessException suggests that the second transaction cached a 'view' of some 'domain' before the first transaction had finished. This must be wrong. The second transaction must (re)create its 'view' once it has exclusive access.

Regards

Ed Willink
Re: Improving containment list performance in CDO/EMF [message #1847011 is a reply to message #1847006] Tue, 12 October 2021 07:43 Go to previous messageGo to next message
Alain Picard is currently offline Alain PicardFriend
Messages: 266
Registered: July 2009
Senior Member
Ed,

I wouldn't consider it a bug from a transaction perspective. If your add got translated to add element at position x and then another transaction happened in the meantime, you get notified of the issue and can retry the transaction. There is no way to know if that position x meant just append to the end of the list, whatever it's at, or do what is said and put it at position x, in which case you should be notified that your referenced view of the element is out of sync. Imagine if you're sorting the list in some fashion, position x could have been the end of the list, but after the other transaction has happened, this can force you to re-evaluate. This is why the semantic of add and add at index are different.

OTOH, if you would submit a real add/append to CDO without any any index, then it can be clear that your intent is to simply append to such list, without any consideration for the position. Then the conflict can be managed in an optimized way.

Alain
Re: Improving containment list performance in CDO/EMF [message #1847015 is a reply to message #1847011] Tue, 12 October 2021 09:25 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Certainly. If you want to perform some 'globally significant' transaction you need a corresponding global lock to give global exclusivity and corresponding loss of concurrency. I do not know enough about the tooling to know whether CDO is too friendly in allowing/mandating the application to take control, or buggy in not inhibiting a clear hazard.

In practice it just seems like a typical example of the concurrency nightmare that I am more familiar with in the case of concurrent edits to UML models mediated by a GIT repo. Merging conflicts between anarchically independent developments is seriously challenging. So I tend to see it as an application responsibility to impose the synchronization that the application can understand and which the too-friendly tooling building blocks cannot.

Regards

Ed Willink
Re: Improving containment list performance in CDO/EMF [message #1847016 is a reply to message #1847011] Tue, 12 October 2021 09:44 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
You're right, AbstractEList.add(E) delegates to addUnique(E), which calls doAddUnique(size(), E) in DelegatingNotifyingListImpl. In CDO that creates a CDOAddFeatureDelta with the insertion index that's computed in the committing client transaction. When that arrives at the server the underlying list/object can already be modified by another client and the insertion index (like any other feature delta in that revision delta) can have become meaningless. Treating an "append" differently is not easily possible because even when one would succeed to create a new kind of CDOAddFeatureDelta this feature delta would have to be interpreted differently in thousand places. More importantly, we can't generally establish that the doAddUnique(size(), E) behavior is NOT the intended behavior; applications could rely on EMF's known behavior.

But CDO offers automatic conflict resolvers on both the client and the server side. On the client side you can add one, for example, as follows:

transaction.options().addConflictResolver(new CDOMergingConflictResolver(new DefaultCDOMerger.PerFeature.ManyValued());


A CDOConflictResolver is comparingly cheap, but conflicts can still happen on the server if timing permits. In addition you can one on the server side, for example, as follows:

repository.setCommitConflictResolver(new ICommitConflictResolver.Merging());


An ICommitConflictResolver attempts to resolve possible conflicts during TransactionCommitContext.computeDirtyObjects().

Both resolvers use a DefaultCDOMerger.PerFeature.ManyValued, which is able to adjust the insertion index of an add() operation, if needed.


Re: Improving containment list performance in CDO/EMF [message #1847017 is a reply to message #1847015] Tue, 12 October 2021 09:52 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Ed Willink wrote on Tue, 12 October 2021 11:25
If you want to perform some 'globally significant' transaction you need a corresponding global lock to give global exclusivity and corresponding loss of concurrency. [...]


CDO supports such pessimistic write locks:

CDOObject.cdoWriteLock().lock(timeout)


or atomically on multiple objects:

CDOView.lockObjects(Collection<? extends CDOObject> objects, LockType lockType, long timeout, boolean recursive) throws InterruptedException;




Re: Improving containment list performance in CDO/EMF [message #1847018 is a reply to message #1847016] Tue, 12 October 2021 09:57 Go to previous messageGo to next message
Alain Picard is currently offline Alain PicardFriend
Messages: 266
Registered: July 2009
Senior Member
Eike,

Thanks for the great info. As you know (from other threads here) we do have a CDOMergingConflictResolver, but not tailored to this and I get the hint to move to current version as 4,7 doesn't have the server side conflict resolution.

That leads me to one more question. How does one know that it is a valid index re-adjustment case. I was thinking that if the feature is not ordered, that is probably a good candidate that doesn't care about the index, but I do have, what is probably the main case, where ordered is true but insertion order is irrelevant. The ordering is set to true, since elements can be manually re-ordered by the user after the fact. Semantically would you see the pattern of add at Integer.MAX_VALUE to be an approach or what other mechanism would you suggest to provide the correct semantic?

Cheers,
Alain
Re: Improving containment list performance in CDO/EMF [message #1847020 is a reply to message #1847018] Tue, 12 October 2021 10:16 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Alain Picard wrote on Tue, 12 October 2021 11:57
Semantically would you see the pattern of add at Integer.MAX_VALUE to be an approach or what other mechanism would you suggest to provide the correct semantic?


Semantically a new CDOFeatureDelta type for "append" would seem to be the right approach. But, as I mentioned before, many technical implications are not clear at this point. And getting it all right would be an extremely expensive undertaking.

It would be much simpler and safer to base the "insert vs. append" decision not on the operation type, but rather on some static feature information. Note that you can extend the DefaultCDOMerger and make it ignore certain features.


Re: Improving containment list performance in CDO/EMF [message #1847021 is a reply to message #1847020] Tue, 12 October 2021 10:21 Go to previous message
Alain Picard is currently offline Alain PicardFriend
Messages: 266
Registered: July 2009
Senior Member
Ok, I guess I can apply the feature is not ordered, append and if feature is ordered, check if it has an annotation of insertAppend and then proceed via the resolvers.

Thanks
Alain
Previous Topic:Reason for: A containment or bidirectional reference must be unique if its upper bound is different
Next Topic:[CDO] Best way to force unlocking view/locking manager
Goto Forum:
  


Current Time: Thu May 02 09:41:38 GMT 2024

Powered by FUDForum. Page generated in 0.06694 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top