[EMAIL PROTECTED] wrote:

> Santiago Gala wrote:
>
> > [EMAIL PROTECTED] wrote:
> >
> > > I'm not sure how a MRU cache would perform under high load, with
> > > some ten-thousands of concurrent users on an app server with a big
> > > thread pool running on a multi-processor machine - there might be
> > > synchronization issues resulting in temporarily blocked threads.
> > >
> > > The MRU cache probably needs synchronization of the methods to
> > > get/remove elements to/from the cache and needs to find/remove
> > > an element of the list and add it at the head of the list for
> > > each cache hit ... You may need to synchronize on the cache while
> > > you are reading and parsing the PSML to get the object structure to
> > > put in the cache. All threads handling concurrent requests that
> > > want to get something from the cache during that time would be
> > > blocked until the cache has been updated. As it takes some time to
> > > read a PSML file from disk and create the object structure that
> > > represents it, it may happen that the threads that cause cache
> > > misses block the threads that would cause cache hits for a
> > > significant amount of time.
> > >
> >
> > I solved a similar problem for the DiskCache (synchronising while a
> > potentially long HTTP request was performed) by maintaining one list
> > of "in process" urls, which would have a vector of Threads requesting
> > the url. All the Threads would wait on the interned url string (unique).
> > When the first THread (the one actually loading the URL) finishes, it
> > calls notify() on the sync interned String.
> >
> > This will limit contention a lot. For the disk cache, it works quite
> > well. (The suggestion of using the url.intern() as a "dock" for the
> > waiting threads came from Ricardo Rocha, and it is bright).
> >
> > For the PortletSetRegistry, it would work as follows:
> >
> > Once a PSML is requested, the system checks if it is being
> > loaded/parsed. If it is, the thread adds to a list and waits. This is
> > fast, and synchronized on the "active urls" list.
> >
> > If it is not, the Thread cheacks (synced on the cache) if the PSML is
> > there. If it is there, it returns the object.
> >
> > If it is not, it adds itself (stil sinced on the cache, and also on the
> > loading list) to the "active" list, gives up the monitor on the cache
> > and the list, and proceeds with the loading/parsing of the resource.
> >
> > Finally (literally "finally {}" on a try/catch) it (synced again) adds
> > the object to the cache, removes itself from the list, notifies any
> > waiting Threads, and proceeds using the PSML object or propagates any
> > Throwable received.
> >
> > Any Thread waiting is notified, and repeats the whole process.
> >
> > There should be little contention in any case, because only one user
> > session is active for any user login (typically) and we would only have
> > to serialize different frames or windows from the same session until
> > the user PSML is parsed and stored in the cache.
>
> I guess this will work, but to some extent it seems like an attempt to
> mitigate a bottleneck that was only introduced by using a central
> datastructure in a concurrent environment instead of sticking to the
> standard session approach.
>
> Obviously, holding the PSML files shared by multiple users only once in
> a MRU cache brings a big performance improvement when all users of a
> group get the same content, but it adds complexity that doesn't pay off
> when users have their own, customized pages.
>
> I guess this is just another argument for pluggable cache implementations.
>
> > >
> > > If we store the object structure once per user session,
> > > all threads can still run in parallel without synchronization.
> > > Application servers can manage sessions, use of self-programmed
> > > caches takes away control from them.
> >
> > We still would need to synchronize session access to the object
> > or else retrieval/parsing. If we don't do it, several threads can
> > have a race condition to parse/store the user PSML in the session
> > (I imagine a setup with frames, where several requests are nearly
> > concurrent on the same session for each hit).
> >
> > >
> > > My feeling is that if you run a portal in an environment where
> > > performance really counts, lets say on a machine with 8+ processors
> > > and some GB of RAM) we may be better off by just accepting a certain
> > > memory footprint per session, calculate the amount of RAM needed an
> > > plug it into the machine. I don't know how big the object tree
> > > representing the PSML can get, but if we assume 40 KB and 10000
> > > concurrent sessions, this would mean a memory usage of only 400 MB.
> > >
> >
> > I would say that currently Jetspeed cannot handle more than a few
> > requests per second. This means that a farm of servers should be used
> > in high load, and it will divide the number of concurrent sessions
> > per server to a more realistic number.
>
> Depends on the machine ;) But you are right, performance of the current
> JetSpeed implementation is surely limited. However, I think we have a
> good chance for big performance improvements in JetSpeed 2.
>
> > >
> > > The other question I have is how we would handle changes of the
> > > user's PSML ? Assume we have a page customizer and a user changes
> > > his page layout. Would the page customizer remove or update the
> > > PSML in the cache ? Or would the cache check whether the file has
> > > changed each time it is accessed ?
> > >
> > > > The only disadvantage I see to the MRU is that it will use a
> > > > little more memory under small load (because the pages will
> > > > be persisted in the cache and not released).
> > > > Once the MRU is full or nearly full, the behavior and cost
> > > > associated to the MRU should be about the same that the cost
> > > > associated to the session cache. Am I missing something here ?
> > >
> > > Behavior under small load does not worry me.
> > >
> > > > > I understand that there are other cases, where PSML files can
> > > > > be shared between users. Is the time consumed for parsing the
> > > > > PSML and generating the object tree that represents it or
> > > > > memory usage per session the problem that you see when using
> > > > > the session approach ?
> > > > >
> > > >
> > > > My main concern about using a session cache is that we're making
> > > > a usage pattern asssumption which may not be true in some
> > > > installations. I'd like the portal engine to be agnostic to usage
> > > > pattern.
> > >
> > > The MRU cache relies on the assumption that it is advantageous
> > > to cache the n last recently used elements. If for example you
> > > have 10000 users with custom pages, who request their home page
> > > every ten minutes (home page, read article, back to home page,
> > > read article, back to home page, read article, ...) you get a
> > > mean of 1000 requests for the home page per minute. If you have a
> > > MRU cache with a size of 11000 you're fine, if the MRU cache can
> > > store 9000 elements, it may happen that you only get cache misses
> > > all the time, because a user's PSML is always discarded just
> > > before the user would have accessed his home page again.
> >
> > We can have the best of both worlds if we add implements
> > HttpSessionBindingListener to the PortletSetFactory object, store
> > it both in the session and as a Singleton, and have configurable
> > behaviour to destroy it when the session expires and the number of
> > stored entries in the SingletonHolder is above a certain value
> > (The servlet engine should unbind any objects in the Session when
> > the session is invalidated).
> >
> > It also looks simple to implement in our current source base.
> >
> > The idea just came to me. What do you think?
>
> I see, we'd e.g. have a CacheService that would try to get the PSML
> from the session, if it would not yet be there it would try to get
> it from the SingletonHolder. When a session would expire, the
> reference counter for the particular object tree would be decreased
> and if it reaches 0, the object would be discarded...

Configurable, so Raphael would say no to:

discard.psml.on.expiry (or whatever parameter we use)

>
>
> Sounds like a workable compromise between Raphaels requirements and
> mine...
>

Raphael, if you don't deeply disagree, I think we have found a compromise :-)

>
> >
> > ...
> >
> > It seems the UserProfiler also does some caching. Would this mean
> > we cache the PSML file in the DiskCache and the object tree that
> > is generated from it in the MRU cache ?
> >
>
> > I don't think there is caching there. Only retrieval of the user PSML,
> > passing through the (missnamed) JetspeedDiskCache. It should be called
> > JetspeedResourceManagerService or something similar. The classes are
> > rather small but I can have read them wrong. The caching is done by
> > the fact the the PortletSetFactory for each PSML is a singleton, stored
> > under the PSML url key.
>
> In some cases there is caching though. We have a setup where the user
> PSMLs are obtained from a remote LDAP server via a servlet that gets
> the PSML out of LDAP and retuens it via HTTP (i.e. we have a central
> server from which all portal servers get user info as required) In this
> case, the JetSpeedDiskCache seems to put the user PSML on the local disk.
>

This is because the JetspeedDiskCache is not working correctly. When we have
configuration about cached elements, it should be local. I think that now, it
should not be cached if the url used to recover it has no protocol, is like
http://localhost or http://127.0.0.1 or http://servername, but maybe there is
a bug.

In the interim, you can patch the isLocal() code to get it working for you.
Beware to look for problems at least in

JetspeedDiskCache
JetspeedDiskCacheEntry
DiskCacheUtils <--- Primary function to test
URLFetcher

as the code is not very clean.

>
> > When the code is refactored, I will send a proposal to have the
> > JetspeedDiskCache as a pluggable ResourceManager service, with API to
> > retrieve, expire, get a Reader or a Writer on a resource, etc. handling
> > parallel requests of the same resource.
>
> That should allow to implement a distributed implementation
> that consists of a HTTP proxy on a dedicated machine and code on each
> portal server that accesses URLs via this proxy.
>
> Best regards,
>
> Thomas
>
> Thomas Schaeck
> IBM Pervasive Computing Division
> Phone: +49-(0)7031-16-3479  e-mail: [EMAIL PROTECTED]
> Address: IBM Deutschland Entwicklung GmbH,
> Schoenaicher Str. 220, 71032 Boeblingen, Germany
>
> --
> --------------------------------------------------------------
> Please read the FAQ! <http://java.apache.org/faq/>
> To subscribe:        [EMAIL PROTECTED]
> To unsubscribe:      [EMAIL PROTECTED]
> Archives and Other:  <http://marc.theaimsgroup.com/?l=jetspeed>
> Problems?:           [EMAIL PROTECTED]



--
--------------------------------------------------------------
Please read the FAQ! <http://java.apache.org/faq/>
To subscribe:        [EMAIL PROTECTED]
To unsubscribe:      [EMAIL PROTECTED]
Archives and Other:  <http://marc.theaimsgroup.com/?l=jetspeed>
Problems?:           [EMAIL PROTECTED]

Reply via email to