deltaspike-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christian Beikov <christian.bei...@gmail.com>
Subject Re: Context capturing and JSF Parallel-Preloading
Date Mon, 11 Apr 2016 12:11:24 GMT
Hello,

I have finally implemented the context capturing which is probably also 
interesting for @Futurable.
The commit also includes code for deleting specific beans from a 
context. This is implemented by using AlterableContext.destroy if 
available and otherwise via OWB/Weld-native mechanisms. Note that there 
are some bugs in the AlterableContext.destroy implementations which 
require some hacks to get around.

Destroying beans is necessary for testing the session and application 
scopes.

The implementation of the context capturing is not really nice since it 
requires some reflection hacks but it gets the job done. Would be nice 
if the CDI spec itself already came with a mechanism to capture contexts ;)

I extended the JSF Playground with an example that can be used to test 
the functionality.

Data1 - Data4 tests create beans in the request thread and check if the 
sub-threads can see the values.
Data5 - Data8 tests create beans in the sub-threads and check if the 
request thread can see the values.

You can find the commit here

https://github.com/beikov/deltaspike/commit/3a15d6c3b804166a51346981aad12c36cd779b7d

I would very much appreciate feedback on the implementation and would 
like to get that code into deltaspike.

Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*
Am 09.04.2016 um 12:34 schrieb Gerhard Petracek:
> #1 you would need large(r) buffers (which might get an issue depending on
> your concrete needs)
> #2 furthermore, you can't use "early flush before the html-body" -> you
> benefit in the first step, but it impacts further optimizations
> #3 if you wait in the callback anyway, you can just do the parallel loading
> (or the delegation to parallel loading) there - that just won't work
> (easily) with a producer-centric style
> #4 page-beans which delegate to other beans (which do almost the same as
> your producers) vs. a producers-only style is imo a choice which depends a
> lot on your application
> (+ el-resolvers of di-frameworks can just provide optimizations if you have
> as few diff. names as possible - per page-request).
>
> based on what i've seen so far in a "typical" jsf-application, the benefit
> you get with such a parallelization isn't that huge - given that you can't
> benefit from other possible optimizations.
>
> regards,
> gerhard
>
>
>
> 2016-04-09 11:59 GMT+02:00 Christian Beikov <christian.beikov@gmail.com>:
>
>> Wouldn't setting the buffer size to an appropriate size deal with the
>> problem with redirecting on an error?
>> We could also await all async loads before exiting the phase listener,
>> thus having loaded everything before the rendering starts.
>>
>> Caching the data in a page bean is of course a possibility, but I moved
>> away from this kind of style because then you have to spread all your data
>> reloads in every possible action method. I find it nicer to define a scope
>> for a producer that most of the time is a perfect fit and if necessary, I
>> can still invalidate it. Having referenced producers now makes it easy to
>> achieve a speedup without having to do anything manually(except for
>> annotating the safe producer methods with the interceptor annotation).
>>
>> Mit freundlichen Grüßen,
>> ------------------------------------------------------------------------
>> *Christian Beikov*
>> Am 09.04.2016 um 11:23 schrieb Gerhard Petracek:
>>
>>> hi @ all,
>>>
>>> i considered something similar some days ago.
>>> (the benefit of @Futureable in combination with @PreRenderView callbacks.)
>>> the main issue is that it isn't a nice idea to start with the rendering
>>> before all data was loaded
>>> (and you know that you don't need to render a diff. page - like an
>>> error-page).
>>>
>>> usually it's enough to cache the loaded data in a page-bean (just load
>>> multiple parts in parallel - e.g. in a @PreRenderView callback).
>>>
>>> regards,
>>> gerhard
>>>
>>>
>>>
>>> 2016-04-09 9:55 GMT+02:00 Christian Beikov <christian.beikov@gmail.com>:
>>>
>>> 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 <christian.beikov@gmail.com
>>>>>> :
>>>>> 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 <
>>>>>>> christian.beikov@gmail.com
>>>>>>>
>>>>>>>> :
>>>>>>>>
>>>>>>> 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*
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message