Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Standalone compiled OCL(Problem with GenModel when programatically invoking Java OCL code)
Standalone compiled OCL [message #1777950] Wed, 06 December 2017 16:42 Go to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hello,

I am having trouble running compiled OCL as a standalone Java application. I am using the derived genmodel as the metamodel (which includes the OCL standard library) and when I run the program, I get:

org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Package with uri 'http://www.eclipse.org/emf/2002/GenModel' not found


I have tried running this configuration using standalone interpreted OCL and it works. I have attached the complete project. The main class is test/JavaMMLauncher. Here there is a boolean flag for switching between compiled (based on OCLinEcore) and interpreted OCL (based on Pivot CompleteOCL).

I presume the issue is that the GenModel has not been added to the EPackage.Registry, but GenModel is not accessible. I was wondering if there is a workaround for this, or if the way I'm trying to use the compiled OCL is wrong?

Thanks,
Sina
Re: Standalone compiled OCL [message #1777962 is a reply to message #1777950] Wed, 06 December 2017 20:56 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

The problem is that you invoke

protected OCL ocl = OCL.newInstance(EPackage.Registry.INSTANCE);

which requires that you ensure that EPackage.Registry.INSTANCE is initialized, possibly by using the EcorePlugin.ExtensionProcessor, possibly by OCL's StandaloneProjectMap.inituialzeResourceSet(null). In either case re-using classpath analyses.

If you instead do

protected OCL ocl = OCL.newInstance();

a classpath analysis is done for you. Good if that's all you want. Bad if something else is doing another classpath analysis.

Regards

Ed Willink


Re: Standalone compiled OCL [message #1778196 is a reply to message #1777962] Mon, 11 December 2017 18:27 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Thanks for the solution. Strangely it seems to work on one PC but not on another, both of which have Eclipse Oxygen installed with the latest OCL patch applied. I tried regenerating the genmodel and Java code, even using the same model, metamodel, generated code etc. across both computers and still on one it doesn't fix the issue on the other it does. I presume it's some quirk with EMF or at least the version installed.

On the installation where it fixes the GenModel not found issue, I get another error:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at javaMM.impl.JavaMMFactoryImpl.createMethodDeclaration(JavaMMFactoryImpl.java:849)
	at javaMM.impl.JavaMMFactoryImpl.create(JavaMMFactoryImpl.java:227)
	at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.createObject(XMLHelperImpl.java:885)
	at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.createObject(XMLHelperImpl.java:922)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromFactory(XMLHandler.java:2222)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromTypeName(XMLHandler.java:2132)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObject(XMLHandler.java:2067)
	at org.eclipse.emf.ecore.xmi.impl.XMIHandler.createObject(XMIHandler.java:151)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleFeature(XMLHandler.java:1876)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.processElement(XMLHandler.java:1030)
	at org.eclipse.emf.ecore.xmi.impl.XMIHandler.processElement(XMIHandler.java:82)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:1008)
	at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:719)
	at org.eclipse.emf.ecore.xmi.impl.XMIHandler.startElement(XMIHandler.java:190)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1359)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
	at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.load(XMLLoadImpl.java:175)
	at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doLoad(XMLResourceImpl.java:261)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1518)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1297)
	at org.eclipse.epsilon.evl.engine.test.acceptance.equivalence.StandaloneOCL.preExecute(StandaloneOCL.java:186)
	at org.eclipse.epsilon.profiling.ProfilableRunConfiguration.run(ProfilableRunConfiguration.java:44)
	at test.JavaMMLauncher.main(JavaMMLauncher.java:28)
Caused by: org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException: index=-1, size=0
	at org.eclipse.emf.common.util.BasicEList.get(BasicEList.java:346)
	at javaMM.impl.JavaMMPackageImpl.getAbstractMethodDeclaration__ParametersEffectivelyFinal__DiagnosticChain_Map(JavaMMPackageImpl.java:1123)
	at javaMM.impl.AbstractMethodDeclarationImpl.<clinit>(AbstractMethodDeclarationImpl.java:252)
	... 32 more


Looking at the cause, the problem is in this method of JavaMMPackageImpl:

public EOperation getAbstractMethodDeclaration__ParametersEffectivelyFinal__DiagnosticChain_Map() {
        return getAbstractMethodDeclaration().getEOperations().get(-1);
}


The associated OCL code with this invariant is as follows:

invariant parametersEffectivelyFinal: 
	(self._'body' <> null or self.parameters->isEmpty()) implies (
		self._'body'.statements ->
		selectByKind(ExpressionStatement) ->
		collect(s | s.expression) ->
		selectByKind(Assignment) ->
		select(assignment |
			assignment.leftHandSide.oclIsKindOf(SingleVariableAccess) and
			assignment.operator = '='
		) ->
		isEmpty()
	);



So the only way this could happen is either that the OCL code is wrong, in which case I would expect some error when running the interpretted version. Also given that an identical script was written in EVL and both the interpretted OCL and EVL version give identical results without exceptions, I doubt this could be the issue. Perhaps more likely is that the OCLinEcore version of the constraints is mis-specified, or there is a bug in the code generation.
Re: Standalone compiled OCL [message #1778198 is a reply to message #1778196] Mon, 11 December 2017 19:09 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

ExceptionInInitializerError is often an indication that the true cause is five or six stack frames down. Perhaps some JavaMM library is in the wrong place.

If you can put all your 'good' generated code in a scratch GIT repo, you can then commit the 'bad' code on top and get a nice difference browser. The discrepancy may be obvious. Unfortunatelty the CG is not 100% stable, so some difference may be cosmetic.

For two different machines, I would check your preferences. Particularly the OCL CG default. But better to enforce CG with a GenAnnotation.

Regards

Ed Willink

Re: Standalone compiled OCL [message #1778260 is a reply to message #1778198] Tue, 12 December 2017 11:55 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

I tried regenerating everything again on the PC where GenModel can't be found and got "Failed to pre-generate constraints", despite having set preferences for code generation in Eclipse. I suspect the issue is that GenModel really can't be found!

org.eclipse.ocl.examples.codegen.generator.GenModelException: No GenClass for Boolean
	at org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper.getGenClass(AbstractGenModelHelper.java:313)
	at org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper.getGenOperation(AbstractGenModelHelper.java:442)
	at org.eclipse.ocl.examples.codegen.generator.AbstractGenModelHelper.getGenParameter(AbstractGenModelHelper.java:508)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreAS2CGVisitor.addParameter(OCLinEcoreAS2CGVisitor.java:59)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.getParameter(AS2CGVisitor.java:1088)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreAS2CGVisitor.getParameter(OCLinEcoreAS2CGVisitor.java:70)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.createParameters(AS2CGVisitor.java:493)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitOperation(AS2CGVisitor.java:1520)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitOperation(AS2CGVisitor.java:1)
	at org.eclipse.ocl.pivot.internal.OperationImpl.accept(OperationImpl.java:1488)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.doVisit(AS2CGVisitor.java:504)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitClass(AS2CGVisitor.java:1315)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitClass(AS2CGVisitor.java:1)
	at org.eclipse.ocl.pivot.util.AbstractExtendingVisitor.visitDataType(AbstractExtendingVisitor.java:152)
	at org.eclipse.ocl.pivot.util.AbstractExtendingVisitor.visitPrimitiveType(AbstractExtendingVisitor.java:432)
	at org.eclipse.ocl.pivot.internal.PrimitiveTypeImpl.accept(PrimitiveTypeImpl.java:405)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.doVisit(AS2CGVisitor.java:504)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitPackage(AS2CGVisitor.java:1574)
	at org.eclipse.ocl.examples.codegen.analyzer.AS2CGVisitor.visitPackage(AS2CGVisitor.java:1)
	at org.eclipse.ocl.pivot.util.AbstractExtendingVisitor.visitLibrary(AbstractExtendingVisitor.java:302)
	at org.eclipse.ocl.pivot.internal.LibraryImpl.accept(LibraryImpl.java:350)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreCodeGenerator.generate(OCLinEcoreCodeGenerator.java:401)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreCodeGenerator.generatePackage(OCLinEcoreCodeGenerator.java:354)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreGenModelGeneratorAdapter$OCLinEcoreStateAdapter.createFeatureBodies(OCLinEcoreGenModelGeneratorAdapter.java:485)
	at org.eclipse.ocl.examples.codegen.oclinecore.OCLinEcoreGenModelGeneratorAdapter.doPreGenerate(OCLinEcoreGenModelGeneratorAdapter.java:712)
	at org.eclipse.emf.codegen.ecore.generator.AbstractGeneratorAdapter.preGenerate(AbstractGeneratorAdapter.java:284)
	at org.eclipse.emf.codegen.ecore.generator.Generator.generate(Generator.java:700)
	at org.eclipse.emf.codegen.ecore.genmodel.presentation.GeneratorUIUtil$GeneratorOperation.execute(GeneratorUIUtil.java:178)
	at org.eclipse.ui.actions.WorkspaceModifyOperation.lambda$0(WorkspaceModifyOperation.java:107)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2240)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2267)
	at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:128)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:119)
Re: Standalone compiled OCL [message #1778262 is a reply to message #1778260] Tue, 12 December 2017 12:14 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

That sounds plausible, but not finding the GenClass for Boolean is pretty fundamental.

Very difficult to comment further without a repro.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1778286 is a reply to message #1778262] Tue, 12 December 2017 16:24 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Regarding the ExceptionInInitializerError, I was wondering whether you'd know why this code is generated:

public EOperation getAbstractMethodDeclaration__ParametersEffectivelyFinal__DiagnosticChain_Map() {
        return getAbstractMethodDeclaration().getEOperations().get(-1);
}


I would expect that if the OCL was mis-specified, an exception would be thrown during generation, not silently generating code which is guaranteed to crash at runtime. Is it a bug?

Thanks,
Sina
Re: Standalone compiled OCL [message #1778292 is a reply to message #1778286] Tue, 12 December 2017 16:49 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

You really must provide repros. You don't even tell me what class your snippet was in. Searching for getEOperations().get suggests that the snippet is probably from XXXPackageImpl which is 100% generated by EMF.

get(-1) is clearly very bad. -1 probably comes from an indexOf() that failed to find a guaranteed present value. In some sense your list of operations may be adrift. The list of operations includes constraint implementations, but ParametersEffectivelyFinal doesn't seem like a good constraint name and it lacks the Validate prefix that is applied for my models.

One possible confounding influence may arise if you generate your model more than once without reopening the genmodel editor. The installation of the OCL add-ons performs an in-place modification that IIRC is reverted by a fix for Oxygen. It may be that the reversion is incomplete and causes confusion. Safest to re-open the GenModel editor before any model generation.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1778359 is a reply to message #1778292] Wed, 13 December 2017 13:00 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

I was referring to the problem detailed in the third message, below the first stack trace. Sorry if this wasn't clear.

I tried regenerating again on the computer where everything works and get the same problem with "GenClass for Boolean not found". I'm not doing anything different to what I was before, and the Ecore model hasn't changed. However every time I generate the genmodel, I get HTTP 405 error, perhaps because it's trying to use the model URI as a URL, but this was happening before and the generated code didn't have any compilation errors. I haven't changed the installation of Eclipse with updates or anything of the sort though. Also I found a bug where there are NullPointerExceptions when performing the generation if the parent project has a space in its name. When I tried redoing everything in another project (without space in name), I got GenClass not found again. So finally I tried creating a new workspace and repeating the process. Again I got the same issue.

At this point I'm inclined to abandon using compiled OCL, as I seem to be getting different issues when repeating exactly the same actions on the same files under the same conditions. Once again thanks for your help, but using compiled OCL for a complex metamodel with many constraints in a standalone Java application has been more time-consuming and error-prone than I anticipated.
Re: Standalone compiled OCL [message #1778361 is a reply to message #1778359] Wed, 13 December 2017 13:14 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

You clearly have a problem, but if you decline to provide a repro, there is no way that I can help you, or improve Eclipse OCL for others.

IMHO if you use Open Source software you have a responsibility to try to make it better.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1778388 is a reply to message #1778361] Wed, 13 December 2017 16:41 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

I believe I have provided the necessary files to reproduce the problem in the original post. Everything else is derived from following instructions as outlined in the OCLinEcore code generation tutorial. Again testing with a new workspace using the latest version of Eclipse OCL (http://www.eclipse.org/modeling/download.php?file=/modeling/mdt/ocl/downloads/drops/6.4.0/N201712012043/mdt-ocl-Update-N201712012043.zip), I get these issues. Whilst it's true that anything could be a contributing factor, such as the location of files, operating system, other installed plug-ins, the Eclipse installation etc. it would be infeasible to upload everything.

I would be happy to assist in solving this issue however I do not have the time to learn the Eclipse OCL codebase and how it interacts with EMF, since it's not clear to me whether these issues are with Eclipse OCL or EMF.

Thanks,
Sina
Re: Standalone compiled OCL [message #1778395 is a reply to message #1778388] Wed, 13 December 2017 18:56 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Apologies, your repro was a week ago. Long forgotten.

But I found a bug in that, so I need to see your bug fix.

To use your repro I have to fix a missing preference for 1.8 Java compatibility; my workspace is 1.6 compatibility. I have to add a log4j package import.

I have no idea how running JavaMMLauncher reproduces the problem. It gives me a CCE.

You seem to be observing an unhealthy getEOperations().get(-1). This is source code in your repro. You do not tell me how you generate it.

Playing around I see that I should be genmodeling java_findbugs.genmodel. Once I add a genAnnotation to force OCL CG, it seems to progress slowly across the progress dialog; always encouraging, but your message appears at the end.

The presence of oclstdlib packages is smelly. It suggests that the genmodel is generating rather than re-using. Reloading the genmodel to specify the usedPackage and we get a problem; it fails.

Examining the ecore shows a reference to http://www.eclipse.org/ocl/2015/Library#Collection which is because you declared:

operation getMethods() : Collection(MethodDeclaration)

rather than

operation getMethods() : OrderedSet(MethodDeclaration)

Ecore has no Collection counterpart so you have to use the added complexity of the OCL Standard Library. Probably a bug for me to look at here.

Using OrderedSet, GenModel is much better, no get(-1), but four classes have a code generation bug on EnumerationLiteral equalities. A real bug for me to look at.

(I certainly do not expect you to understand the OCL code base, but you can provide me with a repro and instruction that I can follwo so that I can start debugging in one minute rather much longer guessing.)

Regards

Ed Willink
Re: Standalone compiled OCL [message #1778456 is a reply to message #1778395] Thu, 14 December 2017 11:53 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Use of Collection seems to work only if you emulate the OCL/QVTd tooling and invoke genmodel programmatically with a StandaloneProjectMap to fix up genmodel's metamodel schizophrenia problem. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=528756

Use Bag/OrderedSet/Sequence/Set.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779162 is a reply to message #1778456] Wed, 03 January 2018 11:51 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Having sorted out the OCL and code generation issues, I am now wondering how the generated EValidator should be used? Currently I am loading the model and recursively calling validate() on all contents. However this produces more unsatisfied constraints than expected (5138 vs 2599) and also takes 50 seconds to run (compared to 15 seconds for interpreted)! Clearly something about this approach is not right, but when I tried feeding in the root model element
the validator does not deeply check the containing elements, so it returns immediately with no unsatisfied constraints. Using the manual iteration approach (i.e. calling getAllContents() on the model Resource) and pruning when encountering an invalid element, the number of unsatisfied constraints is still greater than expected (3076) and takes a similar amount of time to run as without pruning.

I have attached a complete self-sufficient example. The method of interest is in javaMM.launch.JavaMMLauncher.loadModelAndCreateDiagnostician(). Here I create a custom Diagnostician and define the validation logic in the method "validateResource(DiagnosticChain diagnostics, Map context)".

Thanks in advance,
Sina

[Updated on: Wed, 03 January 2018 11:56]

Report message to a moderator

Re: Standalone compiled OCL [message #1779171 is a reply to message #1779162] Wed, 03 January 2018 13:13 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

You are not comparing like with like, since the compiled approach gets the benefit of a prune() which might account for the differing unsatisfied counts. However this just makes the slower execution even harder to explain. There is something very wrong and I cannot see that you have made any obvious mistakes. Will investigate further...

(Your memory usage measurements are meaningless. The problem is so big that garbage collection happens. I suspect that what you measure is just luck in terms of how recently garbage was collected.)

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779173 is a reply to message #1779171] Wed, 03 January 2018 13:51 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

The problem is with allInstances() which is a convenient way of writing OCL constraints that execute really slowly on most OCL tools and really really really slowly on naive OCL tools. Few if any optimize to do what you actually meant.

context CatchClause
inv exceptionIsUsed:
SingleVariableAccess.allInstances()->select(variable = self.exception)->notEmpty()

could surely be

context CatchClause
inv exceptionIsUsed:
self.exception.catchClause->notEmpty()

The allInstances() for compiled seems much worse than for interpreted. I've not paid too much attention to this since for QVTd where the metamodel is available a load time analysis is very much more optimized.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=529372 raised

As a rule of thumb. Never ever use allInstances() and try to avoid unnavigable opposites, but prefer an unnavigable opposite to some heroic workaround,

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779204 is a reply to message #1779173] Wed, 03 January 2018 18:59 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Thank you for the suggestions. I am aware that the memory profiling is inconsistent at the moment, but that is an orthogonal concern which I haven't finalized yet. However changing the allInstances() reference in CatchClause seems to have made no difference in performance. It also seems strange to me that passing the root model element to the generated EValidator (in this case, JavaMMValidator) doesn't automatically handle validation in the same way that interpreted OCL does. For reference the following logic is how I run interpreted OCL:
resource.getContents().forEach(eObject -> validator.validate(eObject, diagnostics, context));
Re: Standalone compiled OCL [message #1779207 is a reply to message #1779204] Wed, 03 January 2018 19:38 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

There were two uses of allInstances(). I only suggested an alternative for one of them. I don't have time to solve all your problems.

The difference in deep validation is odd. The lack of deep validation has often irritated me, but you seem to have found it. The many validate methods that lack extensibility are not one of EMF's strong points.

If you are after the ultimate in performance you should code your own traversal that bypasses many of the nested calls and certainly avoids lambdas.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779216 is a reply to message #1779207] Thu, 04 January 2018 06:52 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Your test model has 200,000 lines defining perhaps 20,000 model elements, so based on the performance results in Fig 16 of [1] where speeds approach 1million per second you might expect an execution time of 20 ms. This is only a very rough estimate since your computer may be faster/slower, you don't have to do any output creation, you may have more validation computation per element. Instead you see 20 seconds; a 1000-fold discrepancy.

It is very unlikely that 1000-fold overhead is consumed by necessary work. Something very bad is happening. [1] shows that poor transformation scheduling can go quadratic. In [2] you can see how bad OCL tooling can be on some operations. I already identified allInstances() as bad. It can be cubic in poor implementations. Stepping your example it looked like it was quadratic. The optimizations of [2] are not yet available in Eclipse OCL.

So long as any algorithm is quadratic or worse, that is likely to dominate your performance. But you first need to get a handle on your measuring. You have not yet resolved the difference between compiled/not-compiled tests. So first ensure that both have the same number of validations of the same nodes, and that the validations produce the same results. Depending on what you actually want to measure may affect how you measure it. For instance you might choose to have an unmeasured traversal that puts all the objects in a list so that the measurements of object validation are isolated from the confounding traversal effect, which could be separately instrumented. You might choose to have a very simple failure logging to isolate the cost of BasicDiagnostic maintenance.

First debug to get predictable relevant results for your alternative execution approaches.

Then isolate the non-linear contributors, possibly by commenting out to keep only one algorithm at a time.

While debugging it may help to have a much smaller test model so that you just printf what is happening.

Regards

Ed Willink

[1] http://www.eclipse.org/mmt/qvt/docs/ICMT2017/MicromappingMoC.pdf
[2] http://www.eclipse.org/modeling/mdt/ocl/docs/publications/OCL2017Evaluation/LazyDeterminism.pdf
Re: Standalone compiled OCL [message #1779264 is a reply to message #1779216] Thu, 04 January 2018 15:14 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Thanks again for the suggestions and ideas. I removed calls to allInstances and now the performance is under 3 seconds with the same number of unsatisfied constraints as before (so still incorrect). Also lambdas have a negligible performance impact, especially as I'm not using them in a loop (see [1], for example of one of the optimisations supported at the bytecode level). Regarding the results, the only explanation I can think of for the differences is either a bug in the generated code or subtle differences between OCLinEcore and CompleteOCL semantics, since the former was derived from the latter.

I should also note that the only reason I'm doing this is to compare the performance of compiled and interpreted. It appears that theory and practice do not agree in this case, as the compiled version is apparently not doing the same thing as the interpreted despite seemingly identical inputs.

[1]https://stackoverflow.com/a/30002627/5870336

[Updated on: Thu, 04 January 2018 15:25]

Report message to a moderator

Re: Standalone compiled OCL [message #1779266 is a reply to message #1779264] Thu, 04 January 2018 15:40 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

(I dislike lambdas on many levels; not least because debugging is opaque and I cannot read them. A bit odd given that I'm promoting lambdas for OCL.)

There may be a bug in OCLinEcore and CompleteOCL equivalence; most likely a boxing issue. But I consider this unlikely.

It is very clear that your outer 'loop' is different, so it is not surprising that the inner functionality is different.

If I were debugging it, I would trim to a perhaps 100 element model provided it the discrepancy, then printf all visits and validation attempts and validation results with an alphabetical sort to facilitate a file comparison.

The most likely causes of the differences are:
a) aborting/continuing validation of an element after a first failure
b) validating an element twice
c) omitting an element validation
d) validating a different number of Resources from a RrsourceSet
e) inconsistent error/warning/ignore severity preferences

A printf log will reveal all. In my experience 90% of problems are in the test harness and only 10% in the code under test. But if it proves to be the code under test please raise a Bugzilla.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779285 is a reply to message #1779266] Thu, 04 January 2018 20:27 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

I tried as you suggested and the problem appears to be the difference in the outer loop. I even tried adding all the elements into a Set and yet all of the visited elements were indeed unique (at least according to EObject.equals). It seems that the lack of deep validation is a limitation of EObjectValidator rather than the code generated by OCL. It is puzzling why Diagnostician performs deep validation but EObjectValidator does not. I'll raise a bug in EMF.

Thanks,
Sina

[Updated on: Thu, 04 January 2018 20:28]

Report message to a moderator

Re: Standalone compiled OCL [message #1779316 is a reply to message #1779285] Fri, 05 January 2018 09:36 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

EMF has a 15 year legacy and so any change to EMF carries a very high risk of breaking a legacy application. The validate APIs may be unfortunate but it is very unlikely that they will change in EMF 2.x and there is no sign of the huge amount of cross-project funding necessary to get an EMF 3.x off the ground. The most that might happen is that new methods might support new/clearer functionality. But even that is hard because there are too many methods with too many arguments already; my suggestion of an additional argument to support OCL's customizable diagnostic messages got a WONTFIX. There is no point raising an EMF bug for a dubiously motivated change except to log the issue for the record so that a Bugzilla search discovers the design discussion.

Since the deep Diagnostician / shallow EObjectValidator validation has confused me before, I'll investigate to see if I can understand the design rationale.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779335 is a reply to message #1779316] Fri, 05 January 2018 14:13 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

The design seems clear:
- EObjectValidator validates one EObject
- Diagnostician is a tool that validates an EObject hierarchy; might be nice if it could validate a Resource or ResourceSet too

The problem is that your MyDiagnostician does not override Diagnostician in a compatible fashion.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779344 is a reply to message #1779335] Fri, 05 January 2018 16:10 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

Thanks for looking into this. I'm not sure what you mean by "compatible fashion", since it produces the intended results when using interpreted Complete OCL. For sanity I tried using interpreted OCLinEcore with the same MyDiagnostician and it turns out that they do indeed differ in the number of unsatisfied constraints! Given that I literally copy-pasted the invariants and operations from the CompleteOCL document into the Ecore metamodel (only changing syntax to conform), the differences must be from the semantics or execution of OCLinEcore compared to CompleteOCL. I will go through each invariant until I find the offending ones and report back.
Re: Standalone compiled OCL [message #1779346 is a reply to message #1779344] Fri, 05 January 2018 16:17 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Ho

Diagnostician uses doValidateContents as the hierarchy traversal. MyDiagnostician uses getAllContents().

Regards

Ed Willink
Re: Standalone compiled OCL [message #1779348 is a reply to message #1779346] Fri, 05 January 2018 16:38 Go to previous messageGo to next message
Sina MadaniFriend
Messages: 160
Registered: November 2015
Location: York, UK
Senior Member
Hi Ed,

I actually have two verisons of MyDiagnostician. The one in StandaloneOCL uses the regular doValidateContents. I was referring to that one.

It appears that the generated code was being used somehow (probably due to the genmodel in project plugin.xml). Even though I removed all references to the generated code after putting System.exit in the constructor of the generated validator the program crashed. Deleting the generated code did the trick. Now I'm getting a difference in unsatisfied constraints by only 7 (4357 vs 4350) which is probably an error on my behalf.
Re: Standalone compiled OCL [message #1779352 is a reply to message #1779348] Fri, 05 January 2018 16:54 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Yes. It takes a very great deal more effort to write code that produces a correct/consistent answer rather than just a convenient answer.

Regards

Ed Willink
Re: Standalone compiled OCL [message #1801167 is a reply to message #1779352] Mon, 14 January 2019 19:35 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

While investigating some problems with opposites of template-typed properties, I revisted the earlier example and found a series of howlers in regards to evaluation caches. Every calculation created a new cache, which was particularly unfortunate when allInstances() is used gratuitously within a loop. Fixing the caches dropped execution time from 57 to 6.9 seconds.

Fix is in M1, released today. See https://wiki.eclipse.org/OCL/New_and_Noteworthy/2019-03#Milestone_1

Still more opportinities for improvements: See https://bugs.eclipse.org/bugs/show_bug.cgi?id=543368

Regards

Ed Willink
Previous Topic:import nested packages in CompleteOCL for use with XText
Next Topic:Divide CompleteOCL document into different documents
Goto Forum:
  


Current Time: Tue Apr 16 07:28:15 GMT 2024

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

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

Back to the top