You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Jens Breitenstein <ma...@j-b-s.de> on 2012/07/28 13:11:55 UTC

Rendering cache

Hi T5'ers

we have some performance issues and started thinking about caching our 
pages (lets say parts of them to be precise). Due to the fact we are 
showing user related information along with "public information" on a 
page, we can not make use of a simple web proxy caching.

Therefore we are thinking about a "component rendering result cache".

Assume we have several independent components to show an overview of 
items (and we have a lot of items rendered in a loop) and we want to 
cache the rendering result of one of these particular components for 
several seconds before rendering it again (to reflect new items or 
changes). I am aware this means we are showing stale data for some 
seconds, but honestly this is not an issue because after rendering and 
displaying it in the browser data is considerably old anyway :-)

What might be a good place to intercept the rendering and store the 
output from a component and on the other hand use outputraw for sending 
cached data?
Does anyone tried this before?

Any idea or comment is appreciated, thanks in advance


Jens




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Rendering cache

Posted by Howard Lewis Ship <hl...@gmail.com>.
I hope I'm not violating an NDA when I say that SeeSaw, the big UK
video-on-demand Tapestry project, went down this path. They eventually
turned off a huge amount of the features that, to me, make Tapestry
special, including all dynamically generated JavaScript ... mostly to
support more aggressive caching of full pages, or partial pages.

Anyway, at the end of the day, they found that they could have used
Tapestry almost completely vanilla and it wouldn't have affected their
throughput. Their problems were all elsewhere.

Hopefully, Ben or Alfie is on the list to correct me if what I say is
way off the mark.

How are you identifying that rendering is your bottleneck?  Just how
much are you rendering? What tools are you using to gauge performance,
and how are you identifying rendering vs. database access (when they
can easily be mixed together)?

There are a bunch of options out there, including progressive
enhancement, that require much less re-architecting.

You might find that the issue is database queries during rendering; I
know you've mentioned caching is enabled, but that may not be enough.

I'd look for ways to ensure that rendering is not held up by any
database operations:

- try to do all your db queries up front, and in parallel (tricky with
Hibernate and SQL)
- leverage caching
- watch out for n+1 queries (via tripping over entity relationships)

Finally, you may need to think in terms of a in-memory cacheable
version of your data, optimized for quick access during rendering.
That is, do your queries, and convert your entities into some form of
simple DTO.  I would even think that the DTO could be a collection of
public fields (possibly, immutable public fields).  Tapestry 5.3 is
quite happy to treat a public field just like a property.  The DTOs
could contain just the data needed at render time, and could be
denormalized, which is to say, roll data from relationships and/or
inheritance, as much as possible, into a single object.







On Sat, Jul 28, 2012 at 4:11 AM, Jens Breitenstein <ma...@j-b-s.de> wrote:
> Hi T5'ers
>
> we have some performance issues and started thinking about caching our pages
> (lets say parts of them to be precise). Due to the fact we are showing user
> related information along with "public information" on a page, we can not
> make use of a simple web proxy caching.
>
> Therefore we are thinking about a "component rendering result cache".
>
> Assume we have several independent components to show an overview of items
> (and we have a lot of items rendered in a loop) and we want to cache the
> rendering result of one of these particular components for several seconds
> before rendering it again (to reflect new items or changes). I am aware this
> means we are showing stale data for some seconds, but honestly this is not
> an issue because after rendering and displaying it in the browser data is
> considerably old anyway :-)
>
> What might be a good place to intercept the rendering and store the output
> from a component and on the other hand use outputraw for sending cached
> data?
> Does anyone tried this before?
>
> Any idea or comment is appreciated, thanks in advance
>
>
> Jens
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Rendering cache

Posted by Jens Breitenstein <ma...@j-b-s.de>.
Hi Magnus,

many thanks for the detailed cookbook. I will give it a try and let you 
know and have a nice holiday.


Jens


Am 30.07.12 00:03, schrieb Bård Magnus Kvalheim:
> Hi Jens,
>
> As it happens I too was thinking about this a while back.
> I didn't make any research, but I would probably look into making mixin or
> component using the before and after render phases.
>
> Saving/caching the markup in after - and then short-circuit in before if
> cache is valid. I think is should be possible to get the markup from the
> MarkupWriter.
>
> Providing a cache key as parameter
> (like the 'watch' in
> http://tapestry.apache.org/5.3.4/apidocs/org/apache/tapestry5/annotations/Cached.html
> )
> should be pretty strait forward to implement as well
>
> Some known challenges/limitations:
> * imported javascript/css in inner components
> * use of javascriptsupport in inner components
>
>
> Perhaps I'll give it a crack at it after the vacations if youre still
> looking for a solution.
>
> cheers
> Magnus
>
> On Sat, Jul 28, 2012 at 1:11 PM, Jens Breitenstein<ma...@j-b-s.de>wrote:
>
>> Hi T5'ers
>>
>> we have some performance issues and started thinking about caching our
>> pages (lets say parts of them to be precise). Due to the fact we are
>> showing user related information along with "public information" on a page,
>> we can not make use of a simple web proxy caching.
>>
>> Therefore we are thinking about a "component rendering result cache".
>>
>> Assume we have several independent components to show an overview of items
>> (and we have a lot of items rendered in a loop) and we want to cache the
>> rendering result of one of these particular components for several seconds
>> before rendering it again (to reflect new items or changes). I am aware
>> this means we are showing stale data for some seconds, but honestly this is
>> not an issue because after rendering and displaying it in the browser data
>> is considerably old anyway :-)
>>
>> What might be a good place to intercept the rendering and store the output
>> from a component and on the other hand use outputraw for sending cached
>> data?
>> Does anyone tried this before?
>>
>> Any idea or comment is appreciated, thanks in advance
>>
>>
>> Jens
>>
>>
>>
>>
>> ------------------------------**------------------------------**---------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.**apache.org<us...@tapestry.apache.org>
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Rendering cache

Posted by Bård Magnus Kvalheim <ma...@kvalheim.eu>.
Hi Jens,

As it happens I too was thinking about this a while back.
I didn't make any research, but I would probably look into making mixin or
component using the before and after render phases.

Saving/caching the markup in after - and then short-circuit in before if
cache is valid. I think is should be possible to get the markup from the
MarkupWriter.

Providing a cache key as parameter
(like the 'watch' in
http://tapestry.apache.org/5.3.4/apidocs/org/apache/tapestry5/annotations/Cached.html
)
should be pretty strait forward to implement as well

Some known challenges/limitations:
* imported javascript/css in inner components
* use of javascriptsupport in inner components


Perhaps I'll give it a crack at it after the vacations if youre still
looking for a solution.

cheers
Magnus

On Sat, Jul 28, 2012 at 1:11 PM, Jens Breitenstein <ma...@j-b-s.de>wrote:

> Hi T5'ers
>
> we have some performance issues and started thinking about caching our
> pages (lets say parts of them to be precise). Due to the fact we are
> showing user related information along with "public information" on a page,
> we can not make use of a simple web proxy caching.
>
> Therefore we are thinking about a "component rendering result cache".
>
> Assume we have several independent components to show an overview of items
> (and we have a lot of items rendered in a loop) and we want to cache the
> rendering result of one of these particular components for several seconds
> before rendering it again (to reflect new items or changes). I am aware
> this means we are showing stale data for some seconds, but honestly this is
> not an issue because after rendering and displaying it in the browser data
> is considerably old anyway :-)
>
> What might be a good place to intercept the rendering and store the output
> from a component and on the other hand use outputraw for sending cached
> data?
> Does anyone tried this before?
>
> Any idea or comment is appreciated, thanks in advance
>
>
> Jens
>
>
>
>
> ------------------------------**------------------------------**---------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.**apache.org<us...@tapestry.apache.org>
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: Rendering cache

Posted by Jens Breitenstein <ma...@j-b-s.de>.
Hi Christian!

Many thanks for your answer. Unfortunately, rendering is the expensive 
part, as we already rely on cached data.


Jens


Am 28.07.12 13:49, schrieb Christian Riedel:
> Hi,
>
> I think theres no easy way to intercept the rendered result of a single component (that contains a lot of other components). But you could put this component inside some kind of dummy-page, asynchronously call its url from an internal caching-service and store the output using simple I/O streams.
>
> But that would only make sense if the rendering itself is the expensive part.
> Are you sure that there's no other way of optimizing your code? Rendering a lot of data might also take long because you need to make queries against a database. Maybe you haven't cached the data itself yet?
> You could also think of reducing the amount of items to be displayed on pageload. Is the user able to see all the rendered data without scrolling? If not, you could easily use a lazy loading component to load more data if it's really needed like these:
>
> 	http://www.appelsiini.net/projects/lazyload/enabled.html
> 	http://www.webresourcesdepot.com/load-content-while-scrolling-with-jquery/
>
> Keep the rendering as light as possible!
>
> Best,
> Christian
>
>
> Am 28.07.2012 um 13:11 schrieb Jens Breitenstein:
>
>> Hi T5'ers
>>
>> we have some performance issues and started thinking about caching our pages (lets say parts of them to be precise). Due to the fact we are showing user related information along with "public information" on a page, we can not make use of a simple web proxy caching.
>>
>> Therefore we are thinking about a "component rendering result cache".
>>
>> Assume we have several independent components to show an overview of items (and we have a lot of items rendered in a loop) and we want to cache the rendering result of one of these particular components for several seconds before rendering it again (to reflect new items or changes). I am aware this means we are showing stale data for some seconds, but honestly this is not an issue because after rendering and displaying it in the browser data is considerably old anyway :-)
>>
>> What might be a good place to intercept the rendering and store the output from a component and on the other hand use outputraw for sending cached data?
>> Does anyone tried this before?
>>
>> Any idea or comment is appreciated, thanks in advance
>>
>>
>> Jens
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Rendering cache

Posted by Christian Riedel <cr...@googlemail.com>.
Hi,

I think theres no easy way to intercept the rendered result of a single component (that contains a lot of other components). But you could put this component inside some kind of dummy-page, asynchronously call its url from an internal caching-service and store the output using simple I/O streams.

But that would only make sense if the rendering itself is the expensive part.
Are you sure that there's no other way of optimizing your code? Rendering a lot of data might also take long because you need to make queries against a database. Maybe you haven't cached the data itself yet?
You could also think of reducing the amount of items to be displayed on pageload. Is the user able to see all the rendered data without scrolling? If not, you could easily use a lazy loading component to load more data if it's really needed like these:

	http://www.appelsiini.net/projects/lazyload/enabled.html
	http://www.webresourcesdepot.com/load-content-while-scrolling-with-jquery/

Keep the rendering as light as possible!

Best,
Christian


Am 28.07.2012 um 13:11 schrieb Jens Breitenstein:

> Hi T5'ers
> 
> we have some performance issues and started thinking about caching our pages (lets say parts of them to be precise). Due to the fact we are showing user related information along with "public information" on a page, we can not make use of a simple web proxy caching.
> 
> Therefore we are thinking about a "component rendering result cache".
> 
> Assume we have several independent components to show an overview of items (and we have a lot of items rendered in a loop) and we want to cache the rendering result of one of these particular components for several seconds before rendering it again (to reflect new items or changes). I am aware this means we are showing stale data for some seconds, but honestly this is not an issue because after rendering and displaying it in the browser data is considerably old anyway :-)
> 
> What might be a good place to intercept the rendering and store the output from a component and on the other hand use outputraw for sending cached data?
> Does anyone tried this before?
> 
> Any idea or comment is appreciated, thanks in advance
> 
> 
> Jens
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Rendering cache

Posted by dh ning <ni...@gmail.com>.
Hi, one of my simple implementation, hope it helps.


public abstract class StaticCacheComponent {

    private final static int CACHE_EXPIRED = 60;

    @Inject
    private ComponentResources componentResources;

    @Inject
    private CacheService cacheService;

    @Inject
    private TypeCoercer typeCoercer;

    private Element fakeElement = null;

    private String cacheId = null;

    final boolean beginRender(MarkupWriter writer) {
        InternalComponentResourcesImpl resourcesImpl =
(InternalComponentResourcesImpl)componentResources;
        StringBuilder builder = new
StringBuilder(this.getClass().getSimpleName());
        for (String parameterName :
resourcesImpl.getComponentModel().getParameterNames()) {
            boolean isBound = resourcesImpl.isBound(parameterName);
            String parameterValueStr = null;
            if (isBound) {
                parameterValueStr =
typeCoercer.coerce(resourcesImpl.getBinding(parameterName).get(),
String.class);
            }

builder.append(parameterName).append("_").append(parameterValueStr).append("_");
        }
        cacheId = builder.toString();
        String staticCache = cacheService.getCache(cacheId,
getCacheExpired());
        if (staticCache != null) {
            writer.writeRaw(staticCache);
            return false;
        } else {
            fakeElement = writer.element("span");
            return true;
        }
    }

    final void afterRenderTemplate(MarkupWriter writer) {
        writer.end();
        // must call before removing
        String innerHTMl = fakeElement.getChildMarkup();
        fakeElement.remove();
        writer.writeRaw(innerHTMl);
        cacheService.saveCache(cacheId, getCacheExpired(), innerHTMl);
    }

    protected int getCacheExpired() {
        return CACHE_EXPIRED;
    }
}

2012/7/28 Jens Breitenstein <ma...@j-b-s.de>

> Hi T5'ers
>
> we have some performance issues and started thinking about caching our
> pages (lets say parts of them to be precise). Due to the fact we are
> showing user related information along with "public information" on a page,
> we can not make use of a simple web proxy caching.
>
> Therefore we are thinking about a "component rendering result cache".
>
> Assume we have several independent components to show an overview of items
> (and we have a lot of items rendered in a loop) and we want to cache the
> rendering result of one of these particular components for several seconds
> before rendering it again (to reflect new items or changes). I am aware
> this means we are showing stale data for some seconds, but honestly this is
> not an issue because after rendering and displaying it in the browser data
> is considerably old anyway :-)
>
> What might be a good place to intercept the rendering and store the output
> from a component and on the other hand use outputraw for sending cached
> data?
> Does anyone tried this before?
>
> Any idea or comment is appreciated, thanks in advance
>
>
> Jens
>
>
>
>
> ------------------------------**------------------------------**---------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.**apache.org<us...@tapestry.apache.org>
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>