Commons JCS
  1. Commons JCS
  2. JCS-2

Items read from disk auxilaries are spooled back to disk.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Composite Cache
    • Labels:
      None
    • Environment:
      Any

      Description

      Items that have been read from disk are spooling back to disk. During a large volume of reads, this causes elements that have been read into the cache to be written back to disk, even though there have been no modifications.

      This increase in writes doubles the over all average read time by a factor of 2.

        Activity

        Hide
        Aaron Smuts added a comment -

        A contains method would be too inefficient. Imagine using it on the JDBC disk cache. The update mode solution seems fine for now.

        The only case where items leaving memory would not be present would be if they fell off the disk LRU. A busy item that stays in memory for a long time, time enough for more items than are allowed on disk, would then be missing when it leaves memory. This seems acceptible for now. I'll document the edge case on the disk cache docs.

        Show
        Aaron Smuts added a comment - A contains method would be too inefficient. Imagine using it on the JDBC disk cache. The update mode solution seems fine for now. The only case where items leaving memory would not be present would be if they fell off the disk LRU. A busy item that stays in memory for a long time, time enough for more items than are allowed on disk, would then be missing when it leaves memory. This seems acceptible for now. I'll document the edge case on the disk cache docs.
        Hide
        Aaron Smuts added a comment -

        My solution is not finished.

        In update mode, items are alwasy added to disk when they are put into the cache. They are not put to disk as a swap. The composite cache ignores the swap call when it is in update mode. This won't work, since the memory cache is lru or any given algorithm based and the disk in this pattern would alwasy be FIFO in update more.

        One solution is to add a contains method to the ICache interface. Obviously, this has limited utility for remove clients, since it is often just as cheap to try and get the entire element. However, for the disk cache it is useful. If the disk cache mode is UPDATE, the composite cache will check contains on a swap call. If the disk cache does not contain the item, it will call insert.

        Another option would be to get rid of the disk cache mode idea altogether and to put all the logic down int he disk cache. Since there is some logic in the composite cache already about whether to send items to an auxiliary, it might make the most sense to just leave the mode idea in place.

        I think I'm going to build in the contains method, which will be a bit painful since it will have to be added to all ICache obejcts.

        Show
        Aaron Smuts added a comment - My solution is not finished. In update mode, items are alwasy added to disk when they are put into the cache. They are not put to disk as a swap. The composite cache ignores the swap call when it is in update mode. This won't work, since the memory cache is lru or any given algorithm based and the disk in this pattern would alwasy be FIFO in update more. One solution is to add a contains method to the ICache interface. Obviously, this has limited utility for remove clients, since it is often just as cheap to try and get the entire element. However, for the disk cache it is useful. If the disk cache mode is UPDATE, the composite cache will check contains on a swap call. If the disk cache does not contain the item, it will call insert. Another option would be to get rid of the disk cache mode idea altogether and to put all the logic down int he disk cache. Since there is some logic in the composite cache already about whether to send items to an auxiliary, it might make the most sense to just leave the mode idea in place. I think I'm going to build in the contains method, which will be a bit painful since it will have to be added to all ICache obejcts.
        Hide
        Aaron Smuts added a comment -

        The changes are in CVS. I added tests, updated the changes.xml file, and updated the xdocs.

        Show
        Aaron Smuts added a comment - The changes are in CVS. I added tests, updated the changes.xml file, and updated the xdocs.
        Hide
        Aaron Smuts added a comment -

        I'm adding a configuration option to the CompositeCacheAttributes. It's called DiskUsagePattern. There are two patterns: update and swap. The changes are isolated to the CompositeCache class and they are very easy to unit test.

        SWAP is the default. Under the swap pattern, data is only put to disk when the max memory size is reached. Since items puled from disk are put into memory, if the memory cache is full and you get an item off disk, the lest recently used item will be spooled to disk. If you have a low memory hit ration, you end up thrashing.

        The UPDATE usage pattern allows items to go to disk on an update. It disables the swap. This allows you to persist all items to disk. If you are using the JDBC disk cache for instance, you can get all item on disk use the memory cache for performance, and not worry aobut lossing data on a system crash or improper shutdown. Also, since all items are on disk, there is no need to swap to disk. This prevents the possibility of threashing.

        The configuration is done at the region level. The attrribute is called DiskUsagePatternName and takes two values: SWAP and UPDATE.

        For example, below there is a region defined called "Swap" that uses the SWAP disk usage pattern and another called "Update" that uses the UPDATE usage pattern.

                1. CACHE REGIONS FOR TEST
                  jcs.region.Swap=indexedDiskCache
                  jcs.region.Swap.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
                  jcs.region.Swap.cacheattributes.MaxObjects=100
                  jcs.region.Swap.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache
                  jcs.region.Swap.cacheattributes.DiskUsagePatternName=SWAP

        jcs.region.Update=indexedDiskCache
        jcs.region.Update.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
        jcs.region.Update.cacheattributes.MaxObjects=100
        jcs.region.Update.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache
        jcs.region.Update.cacheattributes.DiskUsagePatternName=UPDATE

        Show
        Aaron Smuts added a comment - I'm adding a configuration option to the CompositeCacheAttributes. It's called DiskUsagePattern. There are two patterns: update and swap. The changes are isolated to the CompositeCache class and they are very easy to unit test. SWAP is the default. Under the swap pattern, data is only put to disk when the max memory size is reached. Since items puled from disk are put into memory, if the memory cache is full and you get an item off disk, the lest recently used item will be spooled to disk. If you have a low memory hit ration, you end up thrashing. The UPDATE usage pattern allows items to go to disk on an update. It disables the swap. This allows you to persist all items to disk. If you are using the JDBC disk cache for instance, you can get all item on disk use the memory cache for performance, and not worry aobut lossing data on a system crash or improper shutdown. Also, since all items are on disk, there is no need to swap to disk. This prevents the possibility of threashing. The configuration is done at the region level. The attrribute is called DiskUsagePatternName and takes two values: SWAP and UPDATE. For example, below there is a region defined called "Swap" that uses the SWAP disk usage pattern and another called "Update" that uses the UPDATE usage pattern. CACHE REGIONS FOR TEST jcs.region.Swap=indexedDiskCache jcs.region.Swap.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes jcs.region.Swap.cacheattributes.MaxObjects=100 jcs.region.Swap.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.region.Swap.cacheattributes.DiskUsagePatternName=SWAP jcs.region.Update=indexedDiskCache jcs.region.Update.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes jcs.region.Update.cacheattributes.MaxObjects=100 jcs.region.Update.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.region.Update.cacheattributes.DiskUsagePatternName=UPDATE
        Hide
        Peter Schwarz added a comment -

        From JCS-3:

        4. I really don't like the change you made to keep the cache from thrashing when the memory is full. The change is pasted below. I don't want to change an element attribute underneath the user, since they may use these attributes to clone addition instances. Attribute changes like this should be explicitly user defined. The general idea is kind of interesting. Perhaps an additional flag, indicating that the item is on disk and does not need to be spooled would be ideal. We are also going to add the ability to treat the disk cache like any other auxiliary, that is, we will not jsut use it as a swap--items will be put to disk and memory simultaneously. In that scenario it is important to keep them from spooling on to disk as well. I'm not sure what the best solution is, but I'll come up with something soon.

        ===================================================================
        — C:/ide/workspace/jcs/src/java/org/apache/jcs/engine/control/CompositeCache.java (revision 426131)
        +++ C:/ide/workspace/jcs/src/java/org/apache/jcs/engine/control/CompositeCache.java (working copy)
        @@ -539,6 +539,10 @@
        // into purgatory
        if ( memCache.getCacheAttributes().getMaxObjects() > 0 )

        { + // We'll set this to false to prevent the element from spooling back to disk. + // If the user changes it, they should do another put anyway, which + // will reset this back to the default value for the cache. + element.getElementAttributes().setIsSpool(false); memCache.update( element ); }

        else

        Show
        Peter Schwarz added a comment - From JCS-3 : 4. I really don't like the change you made to keep the cache from thrashing when the memory is full. The change is pasted below. I don't want to change an element attribute underneath the user, since they may use these attributes to clone addition instances. Attribute changes like this should be explicitly user defined. The general idea is kind of interesting. Perhaps an additional flag, indicating that the item is on disk and does not need to be spooled would be ideal. We are also going to add the ability to treat the disk cache like any other auxiliary, that is, we will not jsut use it as a swap--items will be put to disk and memory simultaneously. In that scenario it is important to keep them from spooling on to disk as well. I'm not sure what the best solution is, but I'll come up with something soon. =================================================================== — C:/ide/workspace/jcs/src/java/org/apache/jcs/engine/control/CompositeCache.java (revision 426131) +++ C:/ide/workspace/jcs/src/java/org/apache/jcs/engine/control/CompositeCache.java (working copy) @@ -539,6 +539,10 @@ // into purgatory if ( memCache.getCacheAttributes().getMaxObjects() > 0 ) { + // We'll set this to false to prevent the element from spooling back to disk. + // If the user changes it, they should do another put anyway, which + // will reset this back to the default value for the cache. + element.getElementAttributes().setIsSpool(false); memCache.update( element ); } else

          People

          • Assignee:
            Aaron Smuts
            Reporter:
            Peter Schwarz
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development