Editable table data loading performance issue [message #1451707] |
Fri, 24 October 2014 07:08 |
Thomas Schär Messages: 4 Registered: February 2014 |
Junior Member |
|
|
Hi!
Assume we have a table with about 15 columns (about 10 of them are editable boolean columns). Unfiltered, it holds rather many data rows (1000+). Now, loading data into the table with the replaceRowsByMatrix(new AtomicReference<Object>(...)) takes a long time. If the editable columns are not editable, the process takes place in reasonable time. Just to show the differences, filling in 19200 non-editable cells took on my machine 319ms, whereas it took over 3 minutes when 12000 of the cells were editable.
I found out, that the execPrepareEdit(...) method is called for each cell, which slows down the processing. So I have overwritten the table's loading method, setting a flag,
@Override
protected void execLoadData(SearchFilter filter) throws ProcessingException {
isInitialLoading = true;
getTable().replaceRowsByMatrix(new AtomicReference<Object>(execLoadTableData(filter)));
isInitialLoading = false;
}
which I then check for in the execPrepareEdit(...) method.
@Override
protected IFormField execPrepareEdit(ITableRow row) throws ProcessingException {
if (getTable().isInitialLoading()) {
return null;
} else {
return super.execPrepareEdit(row);
}
}
With this workaround the loading time is approximately equal with and without editable cells. But is there any danger that something is missed when I just skip the whole execPrepareEdit method? The values are inserted all correctly though, and the table behaves just normal. How did others overcome this problem?
Thanks!
Thomas
|
|
|
|
Re: Editable table data loading performance issue [message #1479526 is a reply to message #1451897] |
Wed, 19 November 2014 14:00 |
Urs Beeli Messages: 573 Registered: October 2012 Location: Bern, Switzerland |
Senior Member |
|
|
I've been able to track this down.
Our initial assumption was, that execPrepareEdit() would be called exactly once when the user clicks into a cell that is editable.
The observed behaviour was that - depending on the table setup - execPrepareEdit() was called many times while filling the table and also when clicking on the row containing an editable cell.
I started tracing a different problem and in its course found the cause for the above issue. The secondary problem was as follows:
I had an AbstractColumn<SomeWrapperClassContainingInformationForCellDecorationAndDisplayStringCreationg>. The wrapper class also contained a list of strings from which a value could be chosen. In order to do this, we decided to use an AbstractSmartField<String>.
Our execPrepareEdit() looked like this:
@Override
protected IFormField execPrepareEdit(ITableRow row) throws ProcessingException {
final SomeWrapperClassContainingInformationForCellDecorationAndDisplayStringCreationg wrapper = getValue(row);
final List<String> values = new ArrayList<>();
values.addAll(wrapper.getResourceTexts());
if (wrapper.isDbMode()) {
values.add(wrapper.getDbText());
}
AbstractSmartField<String> smartField = new AbstractSmartField<String>() {
@Override
protected Class<? extends ILookupCall<String>> getConfiguredLookupCall() {
return OurStringListValueLookupCall.class;
}
@Override
protected void execPrepareLookup(ILookupCall<String> call) throws ProcessingException {
if (call instanceof OurStringListValueLookupCall) {
OurStringListValueLookupCall lookupCall = ((OurStringListValueLookupCall) call);
lookupCall.setValues(values);
lookupCall.setHasDataBaseValue(wrapper.isDbMode());
}
}
};
}
smartField.setValue(wrapper.getSelectedText());
return smartField;
}
However, I was getting class cast exceptions in our LookupCalls getDataByKey() method because the LookupCall<String> could not cast a SomeWrapperClassContainingInformationForCellDecorationAndDisplayStringCreationg object to String.
This irritated me, because I was clearly calling smartField.setValue() with a string parameter. So obviously, some other piece of code was also using my edit field and directly using myColumn.getValue() as input parameter to the setValue() call.
I tracked down the culprit for both issues: AbstractColumn.validateColumnValue()
This method calls prepareEdit() which in turn calls execPrepareEdit() every time it is called and then sets the column content on that field:
editor = prepareEdit(row);
if (editor instanceof IValueField<?>) {
((IValueField<T>) editor).setValue(value);
}
After overriding validateColumnValue() with an empty implementation for my column (no need to validate something chosen from a smart field) all my problems were gone:
- no more class cast exceptions
- only one call to execPrepareEdit exactly once, when I click into an editable cell
I did not track down the reason why validateColumnValue() was being called so often, but it was definitely a lot. In a table with 2 rows, each containing one editable column(), execPrepareEdit() was called 24 times from validateColumnValue() between the opening of the form and the end of initial rendering. Afterwards, each time I clicked on a row it was called 2 more times. With a table that small, this is not tragic. However, in our product we have tables with 2800 rows and 6 columns (of which 2 are editable) and I've had my scout client go into death spasms because several ten thousand instances of AbstractFields were created due to execPreapreEdit calls from validateColumnValue.
So there seem to be two issues:
- wasteful use of resources due to validateColumnValue() causing a new FormField to be created each time it is called (maybe the created form field could be cached on the table cell?)
- problems with the default implementation of validateColumnValue if the types of the Column and the EditField do not match (and there are use cases where this makes sense).
|
|
|
|
Re: Editable table data loading performance issue [message #1514644 is a reply to message #1451707] |
Wed, 17 December 2014 13:29 |
Eclipse User |
|
|
|
Thomas Schär wrote on Fri, 24 October 2014 09:08
With this workaround the loading time is approximately equal with and without editable cells. But is there any danger that something is missed when I just skip the whole execPrepareEdit method? The values are inserted all correctly though, and the table behaves just normal. How did others overcome this problem?
Hi Thomas
editable cells usually validates their values against the editor (form field) of the cell. Therefore there are some (more as expected) instances are created during the initial load of a table. The one and only side effect with your solution 'create the editor only in case the table is already initialized' is that values are not validated against their editors on initial load.
This workaround is practicable and not dangers at all.
/andreas
|
|
|
Re: Editable table data loading performance issue [message #1515897 is a reply to message #1514644] |
Thu, 18 December 2014 13:26 |
Eclipse User |
|
|
|
After analyzing the issue described is not so easy to fix.
Scout tables validate the input set to the table initially. So in case of editable cells the validation id passed to the editors the only way to have not a duplicated validation. The reason for several calls of the validation is the incremental data load.
Now we could discuss if a table should validate the data set to it or not. But this discussion has to take place in the new validation concept and not only for a single field (in this case the table). BUG 455621 is facing this issues.
To have a workaround so far use the way described by Thomas (first message in this thread) with an try... finally to to ensure the guard gets reset in all cases.
-andreas
|
|
|
Powered by
FUDForum. Page generated in 0.04334 seconds