Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-2889

Remove reference to last page from idle SecondLevelCachePageMap

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Closed
    • Minor
    • Resolution: Won't Fix
    • 1.4.8
    • None
    • wicket
    • None
    • Wicket 1.4.8, Java 1.6.0_20 amd64, Ubuntu Hardy

    Description

      Currently, the last used page per PageMap is kept in memory to avoid deserialization overhead. After looking at a heap dump of my application, I found that this strategy is pretty memory intensive: about 170M for 1500 session (115K per session) in the case of my application.

      To reduce this overhead, I'd suggest to drop the last page for "idle" PageMaps. A PageMap could be considered idle as soon as a user doesn't access a page for 10 minutes. I'd argue that it's pretty unlikely that a user accesses any page after 10 minutes (admittedly depending on the application itself) anyway. In cases the user becomes active again, the deserialization overhead should be acceptable. As our application's sessions expire after 30 minutes, this feature would save 2/3 or about 113M of 170M on memory.

      public void expireLastPage() {
      if (sessionId != null && lastPage instanceof Page) {
      IPageStore store = getPageStore();
      if (store instanceof ISerializationAwarePageStore)

      { lastPage = ((ISerializationAwarePageStore)store).prepareForSerialization(sessionId, page) }

      }
      }

      A LinkedHashMap at application scope could be used to expire idle PageMaps, e.g. using

      private void setLastPage(Page lastPage) {
      this.lastPage = lastPage;

      // (re)add to map
      LinkedHashMap<SecondLevelCachePageMap, Long> map = Application.get().getMetaData(LAST_PAGE_EXPIRE_MAP);
      map.remove(this);
      map.put(this, System.currentTimeMillis());
      }

      A thread could then periodically check for idle PageMaps:

      void run() {
      Iterator<Map.Entry<SecondLevelCachePageMap, Long>> iter = Application.get().getMetaData(LAST_PAGE_EXPIRE_MAP).iterator();
      while (iter.hasNext())

      { Map.Entry<SecondLevelCachePageMap, Long> e = iter.next(); if (isIdle(e.getValue())) break; e.getKey().expireLastPage(); iter.remove(); }

      }

      (the code is just to clarify the idea. for synchronization and encapsulation purposes, the map should certainly be wrapped inside a new class).

      Alternatively, pages could be expired if a configured capacity of the map is exceeded. In this case it would be pretty hard to select a sane default that suits most applications out of the box.

      Please comment if this sound like an acceptable addition. I'd be happy to submit a patch (or at least a a patch that would allow to easily extend the current implementation). I'd really appreciate it this feature would find it's way into 1.4.x, preferably as optionally configurable.

      Attachments

        1. wicket-2889.patch
          10 kB
          Stefan Fussenegger

        Issue Links

          Activity

            People

              jcompagner Johan Compagner
              sfussenegger Stefan Fussenegger
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: