OpenJPA
  1. OpenJPA
  2. OPENJPA-2068

Improve performance of java.util.Calendar fields

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.2.0
    • Fix Version/s: 2.2.0
    • Component/s: jdbc
    • Labels:
      None

      Description

      While doing some performance testing, I've found that we could improve the performance of loading Entities that have java.util.Calendar fields. When loading the data into a Calendar field, we actually create two Calendar instances per field. Normally creating an extra instance wouldn't be that big of a deal, but since creating a Calendar is very expensive I would like to remove creation of the extra instance.

      The call flow is something like this:

      • em.find(...) // find an Entity which has a calendar field
        ... execute query, processing result set...
      • DBDictionary.getCalendar(ResultSet,...) // Here we pull a Timestamp out of the result set, and create an unproxied Calendar instance.
        ...
        // now while trying to store the Calendar into the Entity instance, we find that this type needs to be proxied.
        SingleFieldManager.proxy(...) // Here we create the second Calendar instance, which is a proxied calendar

      I'd like to add a configuration property to DBDictionary that tells the runtime to always create proxied calendar instances. This would remove the creation of the initial un-proxied instance. For a large majority of application which use Calendars this would help.

      As always, there is a catch to this approach. If you were to execute a query such as : em.createQuery("SELECT c.myCal FROM CalendarEntity c where c.id=:id", MyCalendar.class), you would get back a proxied instance. This shouldn't be that big of a deal... but still a bit of a quirk.

        Activity

        Hide
        Albert Lee added a comment -

        Close issue in preparation for 2.2.0 release.

        Show
        Albert Lee added a comment - Close issue in preparation for 2.2.0 release.
        Hide
        Rick Curtis added a comment -

        Committed testcase and code fix to trunk.

        Resolving issue.

        Show
        Rick Curtis added a comment - Committed testcase and code fix to trunk. Resolving issue.
        Hide
        Rick Curtis added a comment -

        The bug we hit resulted in the following exception:

        <openjpa-2.2.0-SNAPSHOT-r422266:1232415 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: This container was loaded in large result set field "[x].entities.LrsEntityA.entitybs", but has been removed from its owning field. Therefore, it can no longer be used.
        at org.apache.openjpa.jdbc.meta.strats.LRSProxyCollection.assertOwner(LRSProxyCollection.java:167)
        at org.apache.openjpa.jdbc.meta.strats.LRSProxyCollection.itr(LRSProxyCollection.java:127)
        at org.apache.openjpa.util.AbstractLRSProxyCollection.iterator(AbstractLRSProxyCollection.java:251)
        at org.apache.openjpa.util.ProxyCollections.addAll(ProxyCollections.java:142)
        at org.apache.openjpa.util.java$util$ArrayList$proxy.addAll(Unknown Source)
        at org.apache.openjpa.kernel.SingleFieldManager.proxy(SingleFieldManager.java:112)
        at org.apache.openjpa.kernel.StateManagerImpl.storeObjectField(StateManagerImpl.java:2602)
        at org.apache.openjpa.jdbc.meta.strats.StoreCollectionFieldStrategy.load(StoreCollectionFieldStrategy.java:524)
        at org.apache.openjpa.jdbc.meta.FieldMapping.load(FieldMapping.java:934)
        at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.load(JDBCStoreManager.java:664)
        at com.ibm.ws.persistence.jdbc.kernel.WsJpaJDBCStoreManager.load(WsJpaJDBCStoreManager.java:130)
        at org.apache.openjpa.kernel.DelegatingStoreManager.load(DelegatingStoreManager.java:117)
        at org.apache.openjpa.kernel.ROPStoreManager.load(ROPStoreManager.java:78)
        at org.apache.openjpa.kernel.StateManagerImpl.loadFields(StateManagerImpl.java:3072)
        at org.apache.openjpa.kernel.StateManagerImpl.loadField(StateManagerImpl.java:3149)
        at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1613)
        at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1598)
        at [x].entities.LrsEntityA.pcGetentitybs(LrsEntityA.java)
        at [x].entities.LrsEntityA.getEntitybs(LrsEntityA.java:49)

        Show
        Rick Curtis added a comment - The bug we hit resulted in the following exception: <openjpa-2.2.0-SNAPSHOT-r422266:1232415 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: This container was loaded in large result set field " [x] .entities.LrsEntityA.entitybs", but has been removed from its owning field. Therefore, it can no longer be used. at org.apache.openjpa.jdbc.meta.strats.LRSProxyCollection.assertOwner(LRSProxyCollection.java:167) at org.apache.openjpa.jdbc.meta.strats.LRSProxyCollection.itr(LRSProxyCollection.java:127) at org.apache.openjpa.util.AbstractLRSProxyCollection.iterator(AbstractLRSProxyCollection.java:251) at org.apache.openjpa.util.ProxyCollections.addAll(ProxyCollections.java:142) at org.apache.openjpa.util.java$util$ArrayList$proxy.addAll(Unknown Source) at org.apache.openjpa.kernel.SingleFieldManager.proxy(SingleFieldManager.java:112) at org.apache.openjpa.kernel.StateManagerImpl.storeObjectField(StateManagerImpl.java:2602) at org.apache.openjpa.jdbc.meta.strats.StoreCollectionFieldStrategy.load(StoreCollectionFieldStrategy.java:524) at org.apache.openjpa.jdbc.meta.FieldMapping.load(FieldMapping.java:934) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.load(JDBCStoreManager.java:664) at com.ibm.ws.persistence.jdbc.kernel.WsJpaJDBCStoreManager.load(WsJpaJDBCStoreManager.java:130) at org.apache.openjpa.kernel.DelegatingStoreManager.load(DelegatingStoreManager.java:117) at org.apache.openjpa.kernel.ROPStoreManager.load(ROPStoreManager.java:78) at org.apache.openjpa.kernel.StateManagerImpl.loadFields(StateManagerImpl.java:3072) at org.apache.openjpa.kernel.StateManagerImpl.loadField(StateManagerImpl.java:3149) at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1613) at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1598) at [x] .entities.LrsEntityA.pcGetentitybs(LrsEntityA.java) at [x] .entities.LrsEntityA.getEntitybs(LrsEntityA.java:49)
        Hide
        Rick Curtis added a comment -

        Reopening this issue as it introduced a new bug that was uncovered through some internal testing.

        Show
        Rick Curtis added a comment - Reopening this issue as it introduced a new bug that was uncovered through some internal testing.
        Hide
        Rick Curtis added a comment -

        The code I committed doesn't have the quirk where you'll get a proxied instance when you issue a query where you only are selecting a Calendar field. Also, this behavior isn't configurable as it is transparent.

        Show
        Rick Curtis added a comment - The code I committed doesn't have the quirk where you'll get a proxied instance when you issue a query where you only are selecting a Calendar field. Also, this behavior isn't configurable as it is transparent.
        Hide
        Rick Curtis added a comment -

        I'm attaching a patch with a bulk of the changes. Obviously this isn't complete, but I want to get something out here.

        Show
        Rick Curtis added a comment - I'm attaching a patch with a bulk of the changes. Obviously this isn't complete, but I want to get something out here.

          People

          • Assignee:
            Rick Curtis
            Reporter:
            Rick Curtis
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development