| Summary: | Rebinding extremely slow | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [RT] Riena | Reporter: | Florian Pirchner <florian.pirchner> | ||||
| Component: | UI | Assignee: | Elias Volanakis <elias> | ||||
| Status: | RESOLVED WORKSFORME | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | achilles.sabine, christian.campo, ekke | ||||
| Version: | 2.0.0 | ||||||
| Target Milestone: | 3.0.0 | ||||||
| Hardware: | Macintosh | ||||||
| OS: | Mac OS X | ||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
The unit test:
public class TextBindingTest {
private Shell shell;
@Test
public void test_SetBinding_BeforeSetBean_Without_Redview() {
shell = new Shell(Display.getDefault(), SWT.NONE);
Text text = new Text(shell, SWT.NONE);
ITextRidget textRidget = (ITextRidget) SwtRidgetFactory
.createRidget(text);
StringBean bean = new StringBean();
// first setup
textRidget.bindToModel(bean, StringBean.PROP_VALUE);
textRidget.updateFromModel();
for (int i = 0; i < 1000; i++) {
Date start = new Date();
bean = new StringBean();
textRidget.bindToModel(bean, StringBean.PROP_VALUE);
textRidget.updateFromModel();
Date end = new Date();
long time = end.getTime() - start.getTime();
if (time > 20) {
Assert.fail(String.format("Took to long. %s runs!", i + 1));
}
}
}
In my opinion rebinding a model indicates a programming error in the application. If you want to rebind a model you should bind to a facade and exchange the model behind the facade.
Example:
public class Person{
private String name;
...
public String getName(){
return name;
}
....
}
public class PersonFacade{
private Person person;
...
public String getName(){
return person.getName();
}
public void setPerson(Person person){
this.person = person;
}
...
}
Hi Steffen, of course, you are right for hand coded applications. But if you are using a generic binding approach, the requirement of rebinding a model to the ridget does not have necessarily to be based on an programming error. In my opinon (2 years ago) this way was the most efficient way of rebinding a model. A generic facade implementation is much more expensive because you need an additional databinding context for your facade and have to use reflection to delegate getters and setters. Today i thought about how i am able to implement a very efficient facade which allows me to use a generic binding information for all kind of bindings. Since the way how redView allows to deal with any kind of beans has dramatically changed in the last 2 years, i am able to build a very efficient facade without a databinding context and nor the use of reflection. Right now i am not sure if it is possible to implement one for all kinds of ridgets. Specially the SelectableRidgets??!! I will see... But nevertheless; the described problem of increasing response times to bind a model to the ridget seems to be a bug. I had another look and found out, that the databinding context seems to add a lot of listeners each time the bind()-method is invoked. In my case about 1.000 listeners had been added in org.eclipse.core.databinding.observable.ChangeManager, which caused the real high response times. In summary: Thanks for the hint according the facade. Will allow redView to be more efficient after the refactoring. And please have a look at the binding problem. Thanks, Flo Hi Flo, this is good feedback. If there is performance degrations, it propably means that there is also waster memory (listeners hanging around) so we should look into it. If disposing the DataBindingContext helps, then we could propably easily do that. Elias. Hi Elias, thanks in advance. So i am having a fallback if the instantiation of a generic facade is to resource costly. Actually i am trying to find a generic facade implementation for all bindings. thanks Flo Investigating. Excellent work Florian! Thank you. By the way: I've narrowed down the issue to the fact that AggregateValidationStatus is not disposed (in rebindToModel()). Fixed in HEAD. Created attachment 185275 [details]
Patch
Already committed - attaching just for reference.
Hi Elias, thanks a lot. Cheers, Flo I believe there is an issue left with this bug. @Elias can you please investigate.... One of the tests for this is I believe ValueBindingSupportTest in method testRebindToModelNoPerfomanceDegratation The build server throws junit.framework.AssertionFailedError: junit.framework.AssertionFailedError: null at org.eclipse.riena.ui.ridgets.ValueBindingSupportTest.testRebindToModelNoPerfomanceDegratation(ValueBindingSupportTest.java:408) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62) at org.eclipse.pde.internal.junit.runtime.UITestApplication$1.run(UITestApplication.java:116) At times (not always). The assert is this: assertTrue((time2 / 2) <= time1); (line 408) So I believe that means that rebinding gets still slower by the factor of 2 after awhile (sometimes). Not sure how to reproduce this. If it happens on my machine, I'll have a look at it. At least I've changed the assert error message to print out the measured times. @Christian: Haven't see this in a while. Reopen if it happens again. |
Hi, actually i am doing a lot of rebinding stuff. This means that i am going to bind a new bean to the same instance of the ridget again and again. The 2nd binding call is between 0-1 ms. After the 29th call i am getting a response time of over 20 ms. Therefore i have implemented a unit test. See attachment. The solution might be to dispose the DataBindingContext in ValueBindingSupport ValueBindingSupport.class public void rebindToModel() { .. .. if (modelBinding != null) { modelBinding.dispose(); getContext().removeBinding(modelBinding); // comment flo -> If i am adding this two lines, rebinding is really fast. getContext().dispose(); context = null; } Cheers, Flo