changeset 17:bfde41acb148

Bug 1716: Reduce getObjectSize() call. reviewed-by: ykubota
author Yasumasa Suenaga <suenaga.yasumasa@lab.ntt.co.jp>
date Fri, 28 Mar 2014 13:15:27 +0900
parents 6086194b2867
children 9c57b65d193b
files agent/ChangeLog agent/src/oopUtil.cpp agent/src/oopUtil.hpp agent/src/snapShotContainer.hpp agent/src/snapShotMain.cpp
diffstat 5 files changed, 135 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ChangeLog	Mon Mar 17 19:52:45 2014 +0900
+++ b/agent/ChangeLog	Fri Mar 28 13:15:27 2014 +0900
@@ -1,3 +1,7 @@
+2014-03-28  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
+
+	* Bug 1716: Reduce getObjectSize() call.
+
 2014-03-17  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
 
 	* Bug 1647: Full mode log archiving does not work when using fifo pipe for gc log
--- a/agent/src/oopUtil.cpp	Mon Mar 17 19:52:45 2014 +0900
+++ b/agent/src/oopUtil.cpp	Fri Mar 28 13:15:27 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file oopUtil.cpp
  * \brief This file is used to getting information inner JVM.<br>
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -1587,27 +1587,6 @@
 /* Function for callback. */
 
 /*!
- * \brief Callback function for snapshot.
- * \param event [in] Callback function.
- * \param oop   [in] A java heap object(OopDesc).
- * \param data  [in] User expected data.
- */
-inline void callbackOops(THeapObjectCallback event, void *oop, void* data) {
-    
-    if (likely(event != NULL)) {
-        jlong size = 0;
-        
-        /* Get object size. */
-        if (likely(getObjectSize != NULL)) {
-            getObjectSize(NULL, (jobject)&oop, &size);
-        }
-        
-        /* Invoke callback. */
-        event(oop, size, data);
-    }
-}
-
-/*!
  * \brief Follow oop field block.
  * \param event     [in] Callback function.
  * \param fieldOops [in] Pointer of field block head.
@@ -1643,7 +1622,7 @@
         if (childOop != NULL && !is_in_permanent(collectedHeap, childOop)) {
             
             /* Invoke callback. */
-            callbackOops(event, childOop, data);
+            event(childOop, data);
         }
     }
 }
@@ -1793,7 +1772,7 @@
 extern "C" void callbackForParallel(void *oop) {
     
     /* Invoke callback by GC. */
-    callbackOops(gcCallbackFunc, oop, NULL);
+    gcCallbackFunc(oop, NULL);
     isInvokedParallelGC = true;
 }
 
@@ -1805,7 +1784,7 @@
 extern "C" void callbackForParOld(void *oop) {
     
     /* Invoke callback by GC. */
-    callbackOops(gcCallbackFunc, oop, NULL);
+    gcCallbackFunc(oop, NULL);
     isInvokedParallelGC = true;
 }
 
@@ -1827,7 +1806,7 @@
   }
 
   /* Invoke snapshot callback. */
-  callbackOops(gcCallbackFunc, *oop, NULL);
+  gcCallbackFunc(*oop, NULL);
 }
 
 /*!
@@ -1861,7 +1840,7 @@
         }
         
         /* Invoke callback by CMS GC. */
-        callbackOops(cmsCallbackFunc, oop, NULL);
+        cmsCallbackFunc(oop, NULL);
     } else if (*useG1) {
         
         if (checkObjectMap->checkAndMark(oop)) {
@@ -1871,7 +1850,7 @@
         }
         
         /* Invoke callback by GC. */
-        callbackOops(gcCallbackFunc, oop, NULL);
+        gcCallbackFunc(oop, NULL);
         isInvokedParallelGC = true;
     }
 }
@@ -1888,7 +1867,7 @@
     if (likely(isMarkedObject(oop))) {
         
         /* Invoke callback by CMS GC. */
-        callbackOops(cmsCallbackFunc, oop, NULL);
+        cmsCallbackFunc(oop, NULL);
     }
 }
 
@@ -1970,7 +1949,7 @@
 extern "C" void callbackForJvmtiIterate(void *oop) {
     
     /* Invoke callback by JVMTI. */
-    callbackOops(jvmtiIteCallbackFunc, oop, NULL);
+    jvmtiIteCallbackFunc(oop, NULL);
 }
 
 /*!
--- a/agent/src/oopUtil.hpp	Mon Mar 17 19:52:45 2014 +0900
+++ b/agent/src/oopUtil.hpp	Fri Mar 28 13:15:27 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file oopUtil.hpp
  * \brief This file is used to getting information inner JVM.<br>
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -71,10 +71,9 @@
 /*!
  * \brief This function is for heap object callback.
  * \param oop  [in] Java heap object(Inner class format).
- * \param size [in] Size of child object instance.
  * \param data [in] User expected data. Always this value is NULL.
  */
-typedef void (*THeapObjectCallback)(void *oop, jlong size, void* data);
+typedef void (*THeapObjectCallback)(void *oop, void* data);
 
 /*!
  * \brief This function is for class oop adjust callback by GC.
--- a/agent/src/snapShotContainer.hpp	Mon Mar 17 19:52:45 2014 +0900
+++ b/agent/src/snapShotContainer.hpp	Fri Mar 28 13:15:27 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapshotContainer.hpp
  * \brief This file is used to add up using size every class.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -76,15 +76,16 @@
  * \brief This structure stored class information.
  */
 typedef struct{
-    jlong tag;               /*!< Class tag.                 */
-    jlong classNameLen;      /*!< Class name.                */
-    char *className;         /*!< Class name length.         */
-    void *klassOop;          /*!< Java inner class object.   */
-    jlong oldTotalSize;      /*!< Class old total use size.  */
-    TOopType oopType;        /*!< Type of class.             */
-    jlong clsLoaderId;       /*!< Class loader instance id.  */
-    jlong clsLoaderTag;      /*!< Class loader class tag.    */
-    bool isRemoved;          /*!< Class is already unloaded. */
+    jlong tag;               /*!< Class tag.                                 */
+    jlong classNameLen;      /*!< Class name.                                */
+    char *className;         /*!< Class name length.                         */
+    void *klassOop;          /*!< Java inner class object.                   */
+    jlong oldTotalSize;      /*!< Class old total use size.                  */
+    TOopType oopType;        /*!< Type of class.                             */
+    jlong clsLoaderId;       /*!< Class loader instance id.                  */
+    jlong clsLoaderTag;      /*!< Class loader class tag.                    */
+    bool isRemoved;          /*!< Class is already unloaded.                 */
+    jlong instanceSize;      /*!< Class size if this class is instanceKlass. */
 } TObjectData;
 
 /*!
--- a/agent/src/snapShotMain.cpp	Mon Mar 17 19:52:45 2014 +0900
+++ b/agent/src/snapShotMain.cpp	Fri Mar 28 13:15:27 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapShotMain.cpp
  * \brief This file is used to take snapshot.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -381,10 +381,9 @@
 /*!
  * \brief Iterate oop field object callback for GC and JVMTI snapshot.
  * \param oop  [in] Java heap object(Inner class format).
- * \param size [in] Size of child object instance.
  * \param data [in] User expected data.
  */
-void iterateFieldObjectCallBack(void *oop, jlong size, void* data) {
+void iterateFieldObjectCallBack(void *oop, void* data) {
     TCollectContainers *containerInfo = (TCollectContainers*)data;
     void *klassOop = getKlassOopFromOop(oop);
     /* Sanity check. */
@@ -416,21 +415,37 @@
     /* Unlock class counter. */
     spinLockRelease(&parentCounter->spinlock);
  
-    if(likely(clsCounter != NULL)){
-      /* Count perent class size and instance count. */
-      localSnapshot->FastInc(clsCounter->counter, size);
+    if(unlikely(clsCounter == NULL)){
+      PRINT_CRIT_MSG("Couldn't get class counter!");
+      return;
     }
 
+    jlong size = 0;
+    if(clsCounter->objData->oopType == otInstance){
+
+      if(likely(clsCounter->objData->instanceSize != 0)){
+        size = clsCounter->objData->instanceSize;
+      }
+      else{
+        getObjectSize(NULL, (jobject)&oop, &size);
+        clsCounter->objData->instanceSize = size;
+      }
+
+    }
+    else{
+      getObjectSize(NULL, (jobject)&oop, &size);
+    }
+
+    /* Count perent class size and instance count. */
+    localSnapshot->FastInc(clsCounter->counter, size);
 }
 
 /*!
  * \brief Calculate size of object and iterate child-class in heap.
  * \param snapshot [in] Snapshot instance.
  * \param oop      [in] Java heap object(Inner class format).
- * \param size     [in] Size of child object instance.
  */
-inline void calculateObjectUsage(TSnapShotContainer *snapshot,
-    void *oop, jlong size) {
+inline void calculateObjectUsage(TSnapShotContainer *snapshot, void *oop){
     
     void *klassOop = getKlassOopFromOop(oop);
     TClassContainer *workClsContainer = clsContainer->getLocalContainer();
@@ -440,104 +455,121 @@
         return;
     }
 
+    TSnapShotContainer *localSnapshot = snapshot->getLocalContainer();
+    if(unlikely(localSnapshot == NULL)){
+      PRINT_CRIT_MSG("Couldn't get local snapshot container!");
+      return;
+    }
+
     snapshot->setIsCleared(false);
     
-    TSnapShotContainer *localSnapshot = snapshot->getLocalContainer();
     TClassCounter *clsCounter = NULL;
     TObjectData *clsData = NULL;
-    if (likely(localSnapshot != NULL)) {
-        
-        /* Get class information. */
-        clsData = getObjectDataFromKlassOop(workClsContainer, klassOop);
-        if (likely(clsData != NULL)) {
-            
-            /* Search class. */
-            clsCounter = localSnapshot->findClass(clsData);
-            if (unlikely(clsCounter == NULL)) {
-                
-                /* Push new loaded class. */
-                clsCounter = localSnapshot->pushNewClass(clsData);
-            }
-            
-            if (likely(clsCounter != NULL)) {
-                
-                /* Count perent class size and instance count. */
-                localSnapshot->FastInc(clsCounter->counter, size);
-            }
-        }
+
+    /* Get class information. */
+    clsData = getObjectDataFromKlassOop(workClsContainer, klassOop);
+    if(unlikely(clsData == NULL)){
+      PRINT_CRIT_MSG("Couldn't get ObjectData!");
+      return;
+    }
+
+    /* Search class. */
+    clsCounter = localSnapshot->findClass(clsData);
+    if(unlikely(clsCounter == NULL)){
+      /* Push new loaded class. */
+      clsCounter = localSnapshot->pushNewClass(clsData);
+    }
+
+    if(unlikely(clsCounter == NULL)){
+      PRINT_CRIT_MSG("Couldn't get class counter!");
+      return;
+    }
+
+    TOopType oopType = clsData->oopType;
+    jlong size = 0;
+
+    if(oopType == otInstance){
+
+      if(likely(clsData->instanceSize != 0)){
+        size = clsData->instanceSize;
+      }
+      else{
+        getObjectSize(NULL, (jobject)&oop, &size);
+        clsData->instanceSize = size;
+      }
+
+    }
+    else{
+      getObjectSize(NULL, (jobject)&oop, &size);
     }
-    
-    if (likely(clsCounter != NULL)) {
-        TOopType oopType = clsData->oopType;
-        
-        /* If oop has no field. */
-        if (!hasOopField(oopType)) {
-            return;
-        }
-        
-        TCollectContainers containerInfo;
-        containerInfo.snapshot     = localSnapshot;
-        containerInfo.counter      = clsCounter;
-        containerInfo.clsContainer = workClsContainer;
-        
-        /* Lock class counter. */
-        spinLockWait(&clsCounter->spinlock);
-        
-        TOopMapBlock *offsets = clsCounter->offsets;
-        int offsetCount       = clsCounter->offsetCount;
-        /* If offset list is unused yet. */
-        if (unlikely(offsets == NULL && offsetCount < 0)) {
-            
-            /* Generate offset list. */
-            generateIterateFieldOffsets(klassOop, oopType,
-                &offsets, &offsetCount);
-            clsCounter->offsets     = offsets;
-            clsCounter->offsetCount = offsetCount;
-        }
-        
-        /* Unlock class counter. */
-        spinLockRelease(&clsCounter->spinlock);
-        
-        /* Iterate non-static field objects. */
-        iterateFieldObject(&iterateFieldObjectCallBack, oop, oopType,
-            &offsets, &offsetCount, &containerInfo);
+
+    /* Count perent class size and instance count. */
+    localSnapshot->FastInc(clsCounter->counter, size);
+
+    /* If oop has no field. */
+    if(!hasOopField(oopType)){
+      return;
     }
+
+    TCollectContainers containerInfo;
+    containerInfo.snapshot     = localSnapshot;
+    containerInfo.counter      = clsCounter;
+    containerInfo.clsContainer = workClsContainer;
+
+    TOopMapBlock *offsets = NULL;
+    int offsetCount       = 0;
+
+    /* Lock class counter. */
+    spinLockWait(&clsCounter->spinlock);
+    {
+      offsets     = clsCounter->offsets;
+      offsetCount = clsCounter->offsetCount;
+
+      /* If offset list is unused yet. */
+      if(unlikely(offsets == NULL && offsetCount < 0)){
+        /* Generate offset list. */
+        generateIterateFieldOffsets(klassOop, oopType, &offsets, &offsetCount);
+        clsCounter->offsets     = offsets;
+        clsCounter->offsetCount = offsetCount;
+      }
+
+    }
+    /* Unlock class counter. */
+    spinLockRelease(&clsCounter->spinlock);
+
+    /* Iterate non-static field objects. */
+    iterateFieldObject(&iterateFieldObjectCallBack, oop, oopType,
+                                       &offsets, &offsetCount, &containerInfo);
 }
 
 /*!
  * \brief Count object size in heap by GC.
  * \param oop  [in] Java heap object(Inner class format).
- * \param size [in] Size of java heap object instance.
  * \param data [in] User expected data. Always this value is NULL.
  */
-void HeapObjectCallbackOnGC(void *oop, jlong size, void* data) {
-    
+void HeapObjectCallbackOnGC(void *oop, void* data){
     /* Calculate and merge to GC snapshot. */
-    calculateObjectUsage(snapshotByGC, oop, size);
+    calculateObjectUsage(snapshotByGC, oop);
 }
 
 /*!
  * \brief Count object size in heap by CMSGC.
  * \param oop  [in] Java heap object(Inner class format).
- * \param size [in] Size of java heap object instance.
  * \param data [in] User expected data. Always this value is NULL.
  */
-void HeapObjectCallbackOnCMS(void *oop, jlong size, void* data) {
-    
+void HeapObjectCallbackOnCMS(void *oop, void* data){
     /* Calculate and merge to CMSGC snapshot. */
-    calculateObjectUsage(snapshotByCMS, oop, size);
+    calculateObjectUsage(snapshotByCMS, oop);
 }
 
 /*!
  * \brief Count object size in heap by JVMTI iterateOverHeap.
  * \param oop  [in] Java heap object(Inner class format).
- * \param size [in] Size of java heap object instance.
  * \param data [in] User expected data. Always this value is NULL.
  */
-void HeapObjectCallbackOnJvmti(void *oop, jlong size, void* data) {
-    
+void HeapObjectCallbackOnJvmti(void *oop, void* data){
     /* Calculate and merge to JVMTI snapshot. */
-    calculateObjectUsage(snapshotByJvmti, oop, size);
+    calculateObjectUsage(snapshotByJvmti, oop);
 }
 
 /*!