I extract the "bindings" map of every UIComponent and analyze all
"simple" expressions further.
Simple expression are ones that don't contain a dot in the expression
string. Since named producers will always have a simple name this will
filter out most of the unnecessary expressions. Then I check whether the
last few expressions resolve to beans and if so, I check if the bean is
annotated with the @PreloadingSafe annotation. If all that is true, then
the bean can be preloaded.
You are right that this might be a considerable overhead. I will have to
check what the performance impact of that strategy is. Still I think
that since it's nicely cacheable, it will only add a few milliseconds
(if at all) the first time the tree is traversed.
What do you think about the strategy? Do you have any ideas how I could
improve it?
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*
Am 09.04.2016 um 09:44 schrieb Thomas Andraschko:
The traversal itself is ok but how do you analyze the expression? I think
you have to do it for every component and every value attribute. Thats
something i would like to avoid.
2016-04-09 9:38 GMT+02:00 Christian Beikov <[email protected]>:
Hello Thomas,
well scanning the tree shouldn't be such a big problem I guess since the
JSF lifecycle already traverses the tree multiple times. Doing it another
time shouldn't do that much damage I think, especially because the
traversal would be aware of the client ids that should be rendered in an
ajax request. I also think that it is fairly easy to optimize since I could
cache the preloadable EL-Expressions along with the client ids that they
belong to for a view. So this would only require a traversal once.
The whole idea and use case for which I am implementing this was to make
the preloading in an automatic fashion without the need to touch the views.
Having a preload tag would be definitely another way, but I would like to
first test the performance impact of scanning the expressions. The preload
tag would also be problematic in the ajax use case since it will probably
be located outside of the components that are rendered.
I was also thinking about collecting statistics for the methods that are
used and try to start preloading opportunistically based on that data.
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*
Am 09.04.2016 um 09:18 schrieb Thomas Andraschko:
Hi Christian,
basically thats an interesting idea, just not sure if we could implement
it
in a nicer way.
I think scanning the component tree and analyzing every EL expression
feels
a little risky and slow.
Using a bytecode library isn't the problem in the JSF module, we already
use there our proxy module.
Couldn't we just reuse our @Futureable?
Sure, the handling in the UI would be little bit different (supplierNames
vs supplierNames.get()) but Future should work, right?
Regards,
Thomas
2016-04-09 8:06 GMT+02:00 Christian Beikov <[email protected]>:
Hello,
I am implementing some POCs for parallel preloading of named producer
methods and think I have a working prototype.
I wanted to know if you are interested in including this into Deltaspike
and if so, how I should contribute it.
It is separated into two parts, one is the context capturing in one
thread
and the possibility to start these contexts for a new thread.
The other part is a phase listener that scans the component tree for
UEL-Expressions that evaluate to a named producer method which is
annotated
with a special interceptor annotation(@PreloadingSafe). These producers
are
then invoked in the before render response phase in parallel. This
currently works by creating a proxy from the returned interface. The
invocation handler behind it, just delegates to the result of the future
that was received by submitting the producer method to an
ExecutorService.
It would be nice if this could also work with non-interface types but
that
would require some bytecode library which I didn't want to introduce yet.
Here some example code:
public class SomeProducerBean {
@PreloadingSafe
@Named
@Produces
@RequestScoped
public List<String> getSupplierNames() { /* Some DB call */ }
}
<html>
...
<ui:repeat value="#{supplierNames}" var="supplName">
#{supplName}
<ui:repeat>
...
</html>
So the rendering until it reaches the ui:repeat runs in parallel to the
preloading of the supplier names. When the JSF-Component tries the
evaluate
the expression it might need to block. Also note that other expressions
will still be evaluated in parallel even if one blocks so this can be a
huge boost for performance.
It's not fully tested yet. The easy case works but I haven't tested more
complex scenarios or possible threading issues yet.
What do you say?
--
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*