You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by JumpStart <ge...@gmail.com> on 2023/01/03 13:29:37 UTC

Re: Avoiding page loading

Thank you Ben. I may have to go this route if I can’t find a way to make the page much lighter to load.

Geoff

> On 28 Dec 2022, at 5:55 pm, Ben Weidig <be...@netzgut.net> wrote:
> 
> Hi Geoff,
> 
> I've read through the SoftReference documentation and as far as I
> understand it the references do only get garbage-collected in case of
> memory-pressure.
> However, the behavior to keep recently used objects is only encouraged, not
> explicitly required.
> 
> Looking over the source code, you mabye can replace PageSource with a
> custom implementation that uses another caching implementation.
> Something like this (untested) code maybe?
> 
> package tapestry;
> 
> import java.lang.ref.SoftReference;
> import java.util.Map;
> 
> import org.apache.tapestry5.commons.util.CollectionFactory;
> import org.apache.tapestry5.internal.services.PageLoader;
> import org.apache.tapestry5.internal.services.PageSourceImpl;
> import org.apache.tapestry5.internal.structure.Page;
> import
> org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer;
> import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
> 
> public class CustomPageSourceImpl extends PageSourceImpl {
> 
>    private PageLoader                       pageLoader;
>    private ComponentRequestSelectorAnalyzer selectorAnalyzer;
> 
>    public CustomPageSourceImpl(PageLoader pageLoader,
> ComponentRequestSelectorAnalyzer selectorAnalyzer) {
>        super(pageLoader, selectorAnalyzer);
>        this.pageLoader = pageLoader;
>        this.selectorAnalyzer = selectorAnalyzer;
> 
>    }
> 
>    private static final record CachedPageKey(String pageName,
> ComponentResourceSelector selector) {
>    }
> 
>    private final Map<CachedPageKey, Object> pageCache =
> CollectionFactory.newConcurrentMap();
> 
>    public Page getPage(String canonicalPageName)
>    {
>        var selector = selectorAnalyzer.buildSelectorForRequest();
> 
>        var key = new CachedPageKey(canonicalPageName, selector);
> 
>        while (true)
>        {
>            Object cachedObject = pageCache.get(key);
> 
>            Page page = null;
>            if (cachedObject instanceof SoftReference<?> ref) {
>                page = ref == null ? null : (Page) ref.get();
>            } else {
>                page = (Page) cachedObject;
>            }
> 
>            if (page != null)
>            {
>                return page;
>            }
>            // In rare race conditions, we may see the same page loaded
> multiple times across
>            // different threads. The last built one will "evict" the
> others from the page cache,
>            // and the earlier ones will be GCed.
> 
>            page = pageLoader.loadPage(canonicalPageName, selector);
> 
>            // TODO: Decide here if how you want to store the Page
> 
>            Object cacheValue = new SoftReference<Page>(page);
> 
>            pageCache.put(key, cacheValue);
>        }
>    }
> }
> 
> I'm not sure what the implications are if a page is kept forever, but as a
> SoftReference isn't guaranteed to be garbage-collected, I don't see an
> immediate downside, except needing more memory.
> 
> Alternatively you could trigger the page with a cron job to keep it
> "fresh", but an overriden service is the more robust solution in my opinion.
> 
> Cheers
> Ben
> 
> On Tue, Dec 27, 2022 at 3:24 PM JumpStart <
> geoff.callender.jumpstart@gmail.com> wrote:
> 
>> Hi,
>> 
>> I have one page in my production app which takes a long time to load -
>> minimum 18 seconds. Once loaded, it is very quick to request. But from time
>> to time throughout the day, when this page is requested Tapestry decides it
>> has to reload it. I presume this is because the page cache uses
>> SoftReference (PageSourceImpl.pageCache) and the page has been garbage
>> collected. For the unlucky user, they have to wait an unbearably long time.
>> Sometimes when the system is under load the request can even time out. Is
>> there a simple, reliable, safe way to prevent it being garbage collected?
>> Or have I misunderstood what’s going on?
>> 
>> Cheers,
>> 
>> Geoff
>> 
>> 
>> ---------------------------------------------------------------------
>> 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