# HG changeset patch # User Yasumasa Suenaga # Date 1395980127 -32400 # Node ID bfde41acb148c7c652bc35ca005071fc516cbbcc # Parent 6086194b28676370aa8f9480da59d6015c9891b4 Bug 1716: Reduce getObjectSize() call. reviewed-by: ykubota diff -r 6086194b2867 -r bfde41acb148 agent/ChangeLog --- 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 + + * Bug 1716: Reduce getObjectSize() call. + 2014-03-17 Yasumasa Suenaga * Bug 1647: Full mode log archiving does not work when using fifo pipe for gc log diff -r 6086194b2867 -r bfde41acb148 agent/src/oopUtil.cpp --- 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.
- * 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); } /*! diff -r 6086194b2867 -r bfde41acb148 agent/src/oopUtil.hpp --- 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.
- * 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. diff -r 6086194b2867 -r bfde41acb148 agent/src/snapShotContainer.hpp --- 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; /*! diff -r 6086194b2867 -r bfde41acb148 agent/src/snapShotMain.cpp --- 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); } /*!