8015237: Parallelize string table scanning during strong root processing

Tue, 18 Jun 2013 12:31:07 -0700

author
johnc
date
Tue, 18 Jun 2013 12:31:07 -0700
changeset 5277
01522ca68fc7
parent 5276
0abfeed51c9e
child 5278
b9d151496930

8015237: Parallelize string table scanning during strong root processing
Summary: Parallelize the scanning of the intern string table by having each GC worker claim a given number of buckets. Changes were also reviewed by Per Liden <per.liden@oracle.com>.
Reviewed-by: tschatzl, stefank, twisti

src/share/vm/classfile/symbolTable.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/symbolTable.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/sharedHeap.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/symbolTable.cpp	Fri Jun 14 08:02:32 2013 +0200
     1.2 +++ b/src/share/vm/classfile/symbolTable.cpp	Tue Jun 18 12:31:07 2013 -0700
     1.3 @@ -598,6 +598,8 @@
     1.4  
     1.5  bool StringTable::_needs_rehashing = false;
     1.6  
     1.7 +volatile int StringTable::_parallel_claimed_idx = 0;
     1.8 +
     1.9  // Pick hashing algorithm
    1.10  unsigned int StringTable::hash_string(const jchar* s, int len) {
    1.11    return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
    1.12 @@ -761,8 +763,18 @@
    1.13    }
    1.14  }
    1.15  
    1.16 -void StringTable::oops_do(OopClosure* f) {
    1.17 -  for (int i = 0; i < the_table()->table_size(); ++i) {
    1.18 +void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
    1.19 +  const int limit = the_table()->table_size();
    1.20 +
    1.21 +  assert(0 <= start_idx && start_idx <= limit,
    1.22 +         err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx));
    1.23 +  assert(0 <= end_idx && end_idx <= limit,
    1.24 +         err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx));
    1.25 +  assert(start_idx <= end_idx,
    1.26 +         err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
    1.27 +                 start_idx, end_idx));
    1.28 +
    1.29 +  for (int i = start_idx; i < end_idx; i += 1) {
    1.30      HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
    1.31      while (entry != NULL) {
    1.32        assert(!entry->is_shared(), "CDS not used for the StringTable");
    1.33 @@ -774,6 +786,27 @@
    1.34    }
    1.35  }
    1.36  
    1.37 +void StringTable::oops_do(OopClosure* f) {
    1.38 +  buckets_do(f, 0, the_table()->table_size());
    1.39 +}
    1.40 +
    1.41 +void StringTable::possibly_parallel_oops_do(OopClosure* f) {
    1.42 +  const int ClaimChunkSize = 32;
    1.43 +  const int limit = the_table()->table_size();
    1.44 +
    1.45 +  for (;;) {
    1.46 +    // Grab next set of buckets to scan
    1.47 +    int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
    1.48 +    if (start_idx >= limit) {
    1.49 +      // End of table
    1.50 +      break;
    1.51 +    }
    1.52 +
    1.53 +    int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
    1.54 +    buckets_do(f, start_idx, end_idx);
    1.55 +  }
    1.56 +}
    1.57 +
    1.58  void StringTable::verify() {
    1.59    for (int i = 0; i < the_table()->table_size(); ++i) {
    1.60      HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
     2.1 --- a/src/share/vm/classfile/symbolTable.hpp	Fri Jun 14 08:02:32 2013 +0200
     2.2 +++ b/src/share/vm/classfile/symbolTable.hpp	Tue Jun 18 12:31:07 2013 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -246,12 +246,19 @@
    2.11    // Set if one bucket is out of balance due to hash algorithm deficiency
    2.12    static bool _needs_rehashing;
    2.13  
    2.14 +  // Claimed high water mark for parallel chunked scanning
    2.15 +  static volatile int _parallel_claimed_idx;
    2.16 +
    2.17    static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
    2.18    oop basic_add(int index, Handle string_or_null, jchar* name, int len,
    2.19                  unsigned int hashValue, TRAPS);
    2.20  
    2.21    oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
    2.22  
    2.23 +  // Apply the give oop closure to the entries to the buckets
    2.24 +  // in the range [start_idx, end_idx).
    2.25 +  static void buckets_do(OopClosure* f, int start_idx, int end_idx);
    2.26 +
    2.27    StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
    2.28                                sizeof (HashtableEntry<oop, mtSymbol>)) {}
    2.29  
    2.30 @@ -277,9 +284,12 @@
    2.31      unlink_or_oops_do(cl, NULL);
    2.32    }
    2.33  
    2.34 -  // Invoke "f->do_oop" on the locations of all oops in the table.
    2.35 +  // Serially invoke "f->do_oop" on the locations of all oops in the table.
    2.36    static void oops_do(OopClosure* f);
    2.37  
    2.38 +  // Possibly parallel version of the above
    2.39 +  static void possibly_parallel_oops_do(OopClosure* f);
    2.40 +
    2.41    // Hashing algorithm, used as the hash value used by the
    2.42    //     StringTable for bucket selection and comparison (stored in the
    2.43    //     HashtableEntry structures).  This is used in the String.intern() method.
    2.44 @@ -315,5 +325,8 @@
    2.45    // Rehash the symbol table if it gets out of balance
    2.46    static void rehash_table();
    2.47    static bool needs_rehashing() { return _needs_rehashing; }
    2.48 +
    2.49 +  // Parallel chunked scanning
    2.50 +  static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
    2.51  };
    2.52  #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
     3.1 --- a/src/share/vm/memory/sharedHeap.cpp	Fri Jun 14 08:02:32 2013 +0200
     3.2 +++ b/src/share/vm/memory/sharedHeap.cpp	Tue Jun 18 12:31:07 2013 -0700
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -47,7 +47,6 @@
    3.11    SH_PS_SystemDictionary_oops_do,
    3.12    SH_PS_ClassLoaderDataGraph_oops_do,
    3.13    SH_PS_jvmti_oops_do,
    3.14 -  SH_PS_StringTable_oops_do,
    3.15    SH_PS_CodeCache_oops_do,
    3.16    // Leave this one last.
    3.17    SH_PS_NumElements
    3.18 @@ -127,6 +126,8 @@
    3.19  {
    3.20    if (_active) {
    3.21      outer->change_strong_roots_parity();
    3.22 +    // Zero the claimed high water mark in the StringTable
    3.23 +    StringTable::clear_parallel_claimed_index();
    3.24    }
    3.25  }
    3.26  
    3.27 @@ -154,14 +155,16 @@
    3.28    // Global (strong) JNI handles
    3.29    if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
    3.30      JNIHandles::oops_do(roots);
    3.31 +
    3.32    // All threads execute this; the individual threads are task groups.
    3.33    CLDToOopClosure roots_from_clds(roots);
    3.34    CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds);
    3.35 -  if (ParallelGCThreads > 0) {
    3.36 -    Threads::possibly_parallel_oops_do(roots, roots_from_clds_p ,code_roots);
    3.37 +  if (CollectedHeap::use_parallel_gc_threads()) {
    3.38 +    Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, code_roots);
    3.39    } else {
    3.40      Threads::oops_do(roots, roots_from_clds_p, code_roots);
    3.41    }
    3.42 +
    3.43    if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
    3.44      ObjectSynchronizer::oops_do(roots);
    3.45    if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
    3.46 @@ -189,8 +192,12 @@
    3.47      }
    3.48    }
    3.49  
    3.50 -  if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
    3.51 -    if (so & SO_Strings) {
    3.52 +  // All threads execute the following. A specific chunk of buckets
    3.53 +  // from the StringTable are the individual tasks.
    3.54 +  if (so & SO_Strings) {
    3.55 +    if (CollectedHeap::use_parallel_gc_threads()) {
    3.56 +      StringTable::possibly_parallel_oops_do(roots);
    3.57 +    } else {
    3.58        StringTable::oops_do(roots);
    3.59      }
    3.60    }

mercurial