RFR: 8227269: Slow class loading when running JVM in debug mode

Roman Kennke rkennke at redhat.com
Tue Mar 24 20:45:16 UTC 2020


>>> I assume JVMTI maintains separate tagging data for each agent so having
>>> two agents doing tagging won't result in confusion. I didn't actually
>>> find this in the spec. Would be nice to confirm that it is the case.
>>> However, your implementation does seem to conflict with other uses of
>>> tagging in the debug agent:
>> The tagging data is per-jvmtiEnv. We create and use our own env (private
>> to class-tracking), so this wouldn't conflict with other uses of tags.
>> Could it be a problem that we have a single trackingEnv per JVM, though?
>> /me scratches head.
> Ok. This is an area I'm not familiar with, but the spec does say:
> 
> "Each call to GetEnv creates a new JVM TI connection and thus a new JVM
> TI environment."
> 
> So it looks like what you are doing should be ok. I still think you have
> a bug where you are not deallocating signatures of classes that are
> unloaded. If you think otherwise please point out where this is done.

Signatures that make it out of processUnloading() are deallocated in
eventHandler.c, in synthesizeUnload(), right after it has been used.

http://hg.openjdk.java.net/jdk/jdk/file/b9562cc25fc0/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c#l527

Pending signatures on debug-agent-disconnect are deallocated in
classTrack.c, in the reset() routine.

Thanks,
Roman

> thanks,
> 
> Chris
>>> What would cause classTrack_addPreparedClass() to be called for a Class
>>> you've already seen? I don't understand the need for the "tag != 0l"
>>> check.
>> It's probably not needed, may be a left-over from previous installments
>> of this implementation. I will check it, and turn into an assert or so.
>>
>> Thanks,
>> Roman
>>
>>> thanks,
>>>
>>> Chris
>>>
>>> On 3/20/20 12:52 PM, Chris Plummer wrote:
>>>> On 3/20/20 8:30 AM, Roman Kennke wrote:
>>>>> I believe I came up with a much simpler solution that also solves the
>>>>> problems of the existing one, and the ones I proposed earlier.
>>>>>
>>>>> It turns out that we can take advantage of the fact that we can use
>>>>> *anything* as tags in JVMTI, even pointers to stuff (this is
>>>>> explicitely
>>>>> mentioned in the JVMTI spec). This means we can simply stick a pointer
>>>>> to the signature of a class into the tag, and pull it out again
>>>>> when we
>>>>> get notified that the class gets unloaded.
>>>>>
>>>>> This means we don't need an extra data-structure to keep track of
>>>>> classes and signatures, and it also makes the story around locking
>>>>> *much* simpler. Performance-wise this is O(1), i.e. no scanning of all
>>>>> classes needed (as in the current implementation) and no searching of
>>>>> table needed (like in my previous attempts).
>>>>>
>>>>> Please review this new revision:
>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.06/
>>>> I'll have a look at this.
>>>>> (Notice that there still appears to be a performance bottleneck with
>>>>> class-unloading when an actual debugger is attached. This doesn't seem
>>>>> to be related to the classTrack.c implementation though, but looks
>>>>> like
>>>>> a consequence of getting all those class-unload notifications over the
>>>>> wire. My testcase generates 1000s of them, and it's clogging up the
>>>>> buffers.)
>>>> At least this is only a one-shot hit when the classes are unloaded,
>>>> and the performance hit is based on the number of classes being
>>>> unloaded. The main issue is happening every GC, and is O(n) where n is
>>>> the number of loaded classes.
>>>>> I am not sure why jdb needs to enable class-unload listener always. A
>>>>> simple hack disables it, and performance is brilliant, even when
>>>>> jdb is
>>>>> attached:
>>>>> http://cr.openjdk.java.net/~rkennke/disable-jdk-class-unload.patch
>>>> This is JDI, not jdb. It looks like it needs ClassUnload events so it
>>>> can maintain typesBySignature, which is used by public APIs like
>>>> allClasses(). So we have caching of loaded classes both in the debug
>>>> agent and in JDI.
>>>>
>>>> Chris
>>>>> But this is not in the scope of this bug.)
>>>>>
>>>>> Roman
>>>>>
>>>>>
>>>>> On 3/16/20 8:05 AM, serguei.spitsyn at oracle.com wrote:
>>>>>> Sorry, forgot to complete my comments at the end (see below).
>>>>>>
>>>>>>
>>>>>> On 3/15/20 23:57, serguei.spitsyn at oracle.com wrote:
>>>>>>> Hi Roman,
>>>>>>>
>>>>>>> Thank you for the update and sorry for the latency in review.
>>>>>>>
>>>>>>> Some comments are below.
>>>>>>>
>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.05/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c.frames.html
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> 87 cbTrackingObjectFree(jvmtiEnv* jvmti_env, jlong tag)
>>>>>>>     88 {
>>>>>>> 89 debugMonitorEnter(deletedSignatureLock);
>>>>>>> 90 if (currentClassTag == -1) {
>>>>>>> 91 // Class tracking not initialized, nobody's interested
>>>>>>> 92 debugMonitorExit(deletedSignatureLock);
>>>>>>> 93 return;
>>>>>>>     94     }
>>>>>>> Just a question:
>>>>>>>     Q1: Should the ObjectFree events be disabled for the jvmtiEnv
>>>>>>> that does
>>>>>>>         the class tracking if class tracking has not been
>>>>>>> initialized?
>>>>>>>
>>>>>>> 70 static jlong currentClassTag; I'm thinking if the name is
>>>>>>> better to
>>>>>>> be something like: lastClassTag or highestClassTag.
>>>>>>>
>>>>>>> 99 KlassNode* klass = *klass_ptr;
>>>>>>> 100 102 while (klass != NULL && klass->klass_tag != tag) { 103
>>>>>>> klass_ptr = &klass->next; 104 klass = *klass_ptr;
>>>>>>> 105 } 106 if (klass != NULL || klass->klass_tag != tag) { //
>>>>>>> klass not
>>>>>>> found - ignore.
>>>>>>> 107 debugMonitorExit(deletedSignatureLock);
>>>>>>> 108 return;
>>>>>>>    109     }
>>>>>>>    It seems to me, something is wrong in the condition at L106
>>>>>>> above.
>>>>>>>    Should it be? :
>>>>>>>       if (klass == NULL || klass->klass_tag != tag)
>>>>>>>
>>>>>>>    Otherwise, how can the second check ever work correctly as the
>>>>>>> return
>>>>>>> will always happen when (klass != NULL)?
>>>>>>>
>>>>>>>    There are several places in this file with the the indent:
>>>>>>> 90 if (currentClassTag == -1) {
>>>>>>> 91 // Class tracking not initialized, nobody's interested
>>>>>>> 92 debugMonitorExit(deletedSignatureLock);
>>>>>>> 93 return;
>>>>>>>     94     }
>>>>>>>    ...
>>>>>>> 152 if (currentClassTag == -1) {
>>>>>>> 153 // Class tracking not initialized yet, nobody's interested
>>>>>>> 154 debugMonitorExit(deletedSignatureLock);
>>>>>>> 155 return;
>>>>>>>    156     }
>>>>>>>    ...
>>>>>>> 161 if (error != JVMTI_ERROR_NONE) {
>>>>>>> 162 EXIT_ERROR(error, "Unable to GetTag with class trackingEnv");
>>>>>>>    163     }
>>>>>>> 164 if (tag != 0l) {
>>>>>>> 165 debugMonitorExit(deletedSignatureLock);
>>>>>>> 166 return; // Already added
>>>>>>>    167     }
>>>>>>>    ...
>>>>>>> 281 cleanDeleted(void *signatureVoid, void *arg)
>>>>>>> 282 {
>>>>>>> 283 char* sig = (char*)signatureVoid;
>>>>>>> 284 jvmtiDeallocate(sig);
>>>>>>> 285 return JNI_TRUE;
>>>>>>>    286 }
>>>>>>>    ...
>>>>>>>    291 void
>>>>>>>    292 classTrack_reset(void)
>>>>>>>    293 {
>>>>>>> 294 int idx;
>>>>>>> 295 debugMonitorEnter(deletedSignatureLock);
>>>>>>> 296
>>>>>>> 297 for (idx = 0; idx < CT_SLOT_COUNT; ++idx) {
>>>>>>> 298 KlassNode* node = table[idx];
>>>>>>> 299 while (node != NULL) {
>>>>>>> 300 KlassNode* next = node->next;
>>>>>>> 301 jvmtiDeallocate(node->signature);
>>>>>>> 302 jvmtiDeallocate(node);
>>>>>>> 303 node = next;
>>>>>>> 304 }
>>>>>>> 305 }
>>>>>>> 306 jvmtiDeallocate(table);
>>>>>>> 307
>>>>>>> 308 bagEnumerateOver(deletedSignatureBag, cleanDeleted, NULL);
>>>>>>> 309 bagDestroyBag(deletedSignatureBag);
>>>>>>> 310
>>>>>>> 311 currentClassTag = -1;
>>>>>>> 312
>>>>>>> 313
>>>>>>> (void)JVMTI_FUNC_PTR(trackingEnv,DisposeEnvironment)(trackingEnv);
>>>>>>> 314 trackingEnv = NULL;
>>>>>>> 315
>>>>>>> 316 debugMonitorExit(deletedSignatureLock);
>>>>>>>
>>>>>>> Could you, please, fix several comments below?
>>>>>>> 63 * The JVMTI tracking env to keep track of klass tags, for
>>>>>>> class-unloads
>>>>>>>    The comma is not needed.
>>>>>>>    Would it better to replace: klass tags => klass_tag's ?
>>>>>>>
>>>>>>>
>>>>>>> 73 * Lock to keep table, currentClassTag and deletedSignatureBag
>>>>>>> consistent
>>>>>>>    Maybe: Lock to guard ... or lock to keep integrity of ...
>>>>>>>
>>>>>>> 84 * Callback when classes are freed, Finds the signature and
>>>>>>> remembers it in deletedSignatureBag. Would be better to use words
>>>>>>> like
>>>>>>> "store" or "record", "Find" should not start from capital letter:
>>>>>>> Invoke the callback when classes are freed, find and record the
>>>>>>> signature in deletedSignatureBag.
>>>>>>>
>>>>>>> 96 // Find deleted KlassNode 133 // Class tracking not initialized,
>>>>>>> nobody's interested 153 // Class tracking not initialized yet,
>>>>>>> nobody's interested 158 /* Check this is not a duplicate */
>>>>>>> Missed dot
>>>>>>> at the end. 106 if (klass != NULL || klass->klass_tag != tag) { //
>>>>>>> klass not found - ignore. In opposite, dot is not needed as the
>>>>>>> comment does not start from a capital letter. 111 // At this
>>>>>>> point we
>>>>>>> have the KlassNode corresponding to the tag
>>>>>>> 112 // in klass, and the pointer to it in klass_node.
>>>>>>    The comment above can be better. Maybe, something like:
>>>>>>      " At this point, we found the KlassNode matching the klass
>>>>>> tag(and it is
>>>>>> linked).
>>>>>>
>>>>>>> 113 // Remember the unloaded signature.
>>>>>>    Better: Record the signature of the unloaded class and unlink it.
>>>>>>
>>>>>> Thanks,
>>>>>> Serguei
>>>>>>
>>>>>>> Thanks,
>>>>>>> Serguei
>>>>>>>
>>>>>>> On 3/9/20 05:39, Roman Kennke wrote:
>>>>>>>> Hello all,
>>>>>>>>
>>>>>>>> Can I please get reviews of this change? In the meantime, we've
>>>>>>>> done
>>>>>>>> more testing and also field-/torture-testing by a customer who is
>>>>>>>> happy
>>>>>>>> now. :-)
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Roman
>>>>>>>>
>>>>>>>>
>>>>>>>>> Hi Serguei,
>>>>>>>>>
>>>>>>>>> Thanks for reviewing!
>>>>>>>>>
>>>>>>>>> I updated the patch to reflect your suggestions, very good!
>>>>>>>>> It also includes a fix to allow re-connecting an agent after
>>>>>>>>> disconnect,
>>>>>>>>> namely move setup of the trackingEnv and deletedSignatureBag to
>>>>>>>>> _activate() to ensure have those structures after re-connect.
>>>>>>>>>
>>>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.05/
>>>>>>>>>
>>>>>>>>> Let me know what you think!
>>>>>>>>> Roman
>>>>>>>>>
>>>>>>>>>> Hi Roman,
>>>>>>>>>>
>>>>>>>>>> Thank you for taking care about this scalability issue!
>>>>>>>>>>
>>>>>>>>>> I have a couple of quick comments.
>>>>>>>>>>
>>>>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.04/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c.frames.html
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 72 /*
>>>>>>>>>> 73 * Lock to protect deletedSignatureBag
>>>>>>>>>> 74 */
>>>>>>>>>> 75 static jrawMonitorID deletedSignatureLock; 76 77 /*
>>>>>>>>>> 78 * A bag containing all the deleted classes' signatures.
>>>>>>>>>> Must be
>>>>>>>>>> accessed under
>>>>>>>>>> 79 * deletedTagLock,
>>>>>>>>>>     80  */
>>>>>>>>>> 81 struct bag* deletedSignatureBag;
>>>>>>>>>>
>>>>>>>>>>     The comments contradict to each other.
>>>>>>>>>>     I guess, the lock name at line 79 has to be
>>>>>>>>>> deletedSignatureLock
>>>>>>>>>> instead of deletedTagLock.
>>>>>>>>>>     Also, comma at the end must be replaced with dot.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 101 // Tag not found? Ignore.
>>>>>>>>>> 102 if (klass == NULL) {
>>>>>>>>>> 103 debugMonitorExit(deletedSignatureLock);
>>>>>>>>>> 104 return;
>>>>>>>>>> 105 }
>>>>>>>>>>    106
>>>>>>>>>> 107 // Scan linked-list.
>>>>>>>>>> 108 jlong found_tag = klass->klass_tag;
>>>>>>>>>> 109 while (klass != NULL && found_tag != tag) {
>>>>>>>>>> 110 klass_ptr = &klass->next;
>>>>>>>>>> 111 klass = *klass_ptr;
>>>>>>>>>> 112 found_tag = klass->klass_tag;
>>>>>>>>>>    113     }
>>>>>>>>>> 114
>>>>>>>>>> 115 // Tag not found? Ignore.
>>>>>>>>>> 116 if (found_tag != tag) {
>>>>>>>>>> 117 debugMonitorExit(deletedSignatureLock);
>>>>>>>>>> 118 return;
>>>>>>>>>>    119     }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>    The code above can be simplified, so that the lines 101-105
>>>>>>>>>> are not
>>>>>>>>>> needed anymore.
>>>>>>>>>>    It can be something like this:
>>>>>>>>>>
>>>>>>>>>> // Scan linked-list.
>>>>>>>>>> while (klass != NULL && klass->klass_tag != tag) {
>>>>>>>>>> klass_ptr = &klass->next;
>>>>>>>>>> klass = *klass_ptr;
>>>>>>>>>>        }
>>>>>>>>>> if (klass == NULL || klass->klass_tag != tag) { // klass not
>>>>>>>>>> found - ignore.
>>>>>>>>>> debugMonitorExit(deletedSignatureLock);
>>>>>>>>>> return;
>>>>>>>>>>        }
>>>>>>>>>>
>>>>>>>>>> It will take more time when I get a chance to look at the rest.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Serguei
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 12/21/19 13:24, Roman Kennke wrote:
>>>>>>>>>>> Here comes an update that resolves some races that happen when
>>>>>>>>>>> disconnecting an agent. In particular, we need to take the
>>>>>>>>>>> lock on
>>>>>>>>>>> basically every operation, and also need to check whether or not
>>>>>>>>>>> class-tracking is active and return an appropriate result (e.g.
>>>>>>>>>>> an empty
>>>>>>>>>>> list) when we're not.
>>>>>>>>>>>
>>>>>>>>>>> Updated webrev:
>>>>>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.04/
>>>>>>>>>>>
>>>>>>>>>>> Thanks,
>>>>>>>>>>> Roman
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>> So, here comes the O(1) implementation:
>>>>>>>>>>>>
>>>>>>>>>>>> - Whenever a class is 'prepared', it is registered with a tag,
>>>>>>>>>>>> and we
>>>>>>>>>>>> set-up a listener to get notified when it is unloaded.
>>>>>>>>>>>> - Prepared classes are kept in a datastructure that is a
>>>>>>>>>>>> table, which
>>>>>>>>>>>> each entry being the head of a linked-list of KlassNode*. The
>>>>>>>>>>>> table is
>>>>>>>>>>>> indexed by tag % slot-count, and then simply prepend the new
>>>>>>>>>>>> KlassNode*.
>>>>>>>>>>>> This is O(1) operation.
>>>>>>>>>>>> - When we get notified of unloading a class, we look up the
>>>>>>>>>>>> signature of
>>>>>>>>>>>> the reported tag in that table, and remember it in a bag. The
>>>>>>>>>>>> KlassNode*
>>>>>>>>>>>> is then unlinked from the table and deallocated. This is ~O(1)
>>>>>>>>>>>> operation
>>>>>>>>>>>> too, depending on the depth of the table. In my testcase which
>>>>>>>>>>>> hammered
>>>>>>>>>>>> the code with class-loads and unloads, I usually see depths of
>>>>>>>>>>>> like 2-3,
>>>>>>>>>>>> but not usually more. It should be ok.
>>>>>>>>>>>> - when processUnloads() gets called, we simply hand out that
>>>>>>>>>>>> bag, and
>>>>>>>>>>>> allocate a new one.
>>>>>>>>>>>> - I also added cleanup-code in classTrack_reset() to avoid
>>>>>>>>>>>> leaking the
>>>>>>>>>>>> signatures and KlassNode* etc when debug agent gets detached
>>>>>>>>>>>> and/or
>>>>>>>>>>>> re-attached (was missing before).
>>>>>>>>>>>> - I also added locks around data-structure-manipulation (was
>>>>>>>>>>>> missing
>>>>>>>>>>>> before).
>>>>>>>>>>>> - Also, I only activate this whole process when an actual
>>>>>>>>>>>> listener gets
>>>>>>>>>>>> registered on EI_GC_FINISH. This seems to happen right when
>>>>>>>>>>>> attaching a
>>>>>>>>>>>> jdb, not sure why jdb does that though. This may be something
>>>>>>>>>>>> to improve
>>>>>>>>>>>> in the future?
>>>>>>>>>>>>
>>>>>>>>>>>> In my tests, the performance of class-tracking itself looks
>>>>>>>>>>>> really good.
>>>>>>>>>>>> The bottleneck now is clearly actual synthesizing the
>>>>>>>>>>>> class-unload
>>>>>>>>>>>> events. I don't see how this can be helped when the debug
>>>>>>>>>>>> agent asks for it?
>>>>>>>>>>>>
>>>>>>>>>>>> Updated webrev:
>>>>>>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.03/
>>>>>>>>>>>>
>>>>>>>>>>>> Please let me know what you think of it.
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>> Roman
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Alright, the perfectionist in me got me. I am implementing
>>>>>>>>>>>>> the even more
>>>>>>>>>>>>> efficient ~O(1) class tracking. Please hold off reviewing for
>>>>>>>>>>>>> now.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks,Roman
>>>>>>>>>>>>>
>>>>>>>>>>>>>    Hi Chris,
>>>>>>>>>>>>>>> I'll have a look at this, although it might not be for a
>>>>>>>>>>>>>>> few days. In
>>>>>>>>>>>>>>> the meantime, maybe you can describe your new
>>>>>>>>>>>>>>> implementation in
>>>>>>>>>>>>>>> classTrack.c so it's easier to look through the changes.
>>>>>>>>>>>>>> Sure.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The purpose of this class-tracking is to be able to
>>>>>>>>>>>>>> determine the
>>>>>>>>>>>>>> signatures of unloaded classes when GC/class-unloading
>>>>>>>>>>>>>> happened, so that
>>>>>>>>>>>>>> we can generate the appropriate JDWP event.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The current implementation does so by maintaining a table of
>>>>>>>>>>>>>> currently
>>>>>>>>>>>>>> prepared classes by building that table when classTrack is
>>>>>>>>>>>>>> initialized,
>>>>>>>>>>>>>> and then add new classes whenever a class gets loaded. When
>>>>>>>>>>>>>> unloading
>>>>>>>>>>>>>> occurs, that cache is rebuilt into a new table, and compared
>>>>>>>>>>>>>> with the
>>>>>>>>>>>>>> old table, and whatever is in the old, but not in the new
>>>>>>>>>>>>>> table gets
>>>>>>>>>>>>>> returned. The problem is that when GCs happen frequently
>>>>>>>>>>>>>> and/or many
>>>>>>>>>>>>>> classes get loaded+unloaded, this amounts to
>>>>>>>>>>>>>> O(classCount*gcCount)
>>>>>>>>>>>>>> complexity.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The new implementation keeps a linked-list of prepared
>>>>>>>>>>>>>> classes, and also
>>>>>>>>>>>>>> tracks unloads via the listener cbTrackingObjectFree().
>>>>>>>>>>>>>> Whenever an
>>>>>>>>>>>>>> unload/GC occurs, the list of prepared classes is scanned,
>>>>>>>>>>>>>> and classes
>>>>>>>>>>>>>> that are also in the deletedTagBag are unlinked (thus
>>>>>>>>>>>>>> maintaining the
>>>>>>>>>>>>>> prepared-classes-list) and its signature put in the list
>>>>>>>>>>>>>> that gets returned.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The implementation is not perfect. In order to determine
>>>>>>>>>>>>>> whether or not
>>>>>>>>>>>>>> a class is unloaded, it needs to scan the deletedTagBag.
>>>>>>>>>>>>>> That process is
>>>>>>>>>>>>>> therefore still O(unloadedClassCount). The assumption here
>>>>>>>>>>>>>> is that
>>>>>>>>>>>>>> unloadedClassCount << classCount. In my experiments this
>>>>>>>>>>>>>> seems to be
>>>>>>>>>>>>>> true, and also reasonable to expect.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> (I have some ideas how to improve the implementation to
>>>>>>>>>>>>>> ~O(1) but it
>>>>>>>>>>>>>> would be considerably more complex: have to maintain a
>>>>>>>>>>>>>> (hash)table that
>>>>>>>>>>>>>> maps tags -> KlassNode*, unlink them directly upon unload,
>>>>>>>>>>>>>> and build the
>>>>>>>>>>>>>> unloaded-signatures list there, but I don't currently see
>>>>>>>>>>>>>> that it's
>>>>>>>>>>>>>> worth the effort).
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> In addition to all that, this process is only activated when
>>>>>>>>>>>>>> there's an
>>>>>>>>>>>>>> actual listener registered for EI_GC_FINISH.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>> Roman
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Chris
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 12/18/19 5:05 AM, Roman Kennke wrote:
>>>>>>>>>>>>>>>> Hello all,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Issue:
>>>>>>>>>>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8227269
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I am proposing what amounts to a rewrite of classTrack.c.
>>>>>>>>>>>>>>>> It avoids
>>>>>>>>>>>>>>>> throwing away the class cache on GC, and instead keeps
>>>>>>>>>>>>>>>> track of
>>>>>>>>>>>>>>>> loaded/unloaded classes one-by-one.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> In addition to that, it avoids this whole dance until an
>>>>>>>>>>>>>>>> agent
>>>>>>>>>>>>>>>> registers interest in EI_GC_FINISH.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Webrev:
>>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~rkennke/JDK-8227269/webrev.01/
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Testing: manual testing of provided test scenarios and
>>>>>>>>>>>>>>>> timing.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Eg with the testcase provided here:
>>>>>>>>>>>>>>>> https://bugzilla.redhat.com/show_bug.cgi?id=1751985
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I am getting those numbers:
>>>>>>>>>>>>>>>> unpatched: no debug: 84s with debug: 225s
>>>>>>>>>>>>>>>> patched:   no debug: 85s with debug: 95s
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I also tested successfully through jdk/submit repo
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Can I please get a review?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>>> Roman
>>>>>>>>>>>>>>>>
>>>>
>>>
> 
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://mail.openjdk.java.net/pipermail/serviceability-dev/attachments/20200324/35657eab/signature-0001.asc>


More information about the serviceability-dev mailing list