author | tschatzl |
Wed, 18 Apr 2018 11:36:48 +0200 | |
changeset 49806 | 2d62570a615c |
parent 47216 | 71c04702a3d5 |
permissions | -rw-r--r-- |
23472 | 1 |
/* |
39452
eebe070746ad
8158871: Long response times with G1 and StringDeduplication
pliden
parents:
35061
diff
changeset
|
2 |
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. |
23472 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
22 |
* |
|
23 |
*/ |
|
24 |
||
30764 | 25 |
#ifndef SHARE_VM_GC_G1_G1STRINGDEDUPTABLE_HPP |
26 |
#define SHARE_VM_GC_G1_G1STRINGDEDUPTABLE_HPP |
|
23472 | 27 |
|
30764 | 28 |
#include "gc/g1/g1StringDedupStat.hpp" |
23472 | 29 |
#include "runtime/mutexLocker.hpp" |
30 |
||
31 |
class G1StringDedupEntryCache; |
|
30175 | 32 |
class G1StringDedupUnlinkOrOopsDoClosure; |
23472 | 33 |
|
34 |
// |
|
35 |
// Table entry in the deduplication hashtable. Points weakly to the |
|
36 |
// character array. Can be chained in a linked list in case of hash |
|
37 |
// collisions or when placed in a freelist in the entry cache. |
|
38 |
// |
|
39 |
class G1StringDedupEntry : public CHeapObj<mtGC> { |
|
40 |
private: |
|
41 |
G1StringDedupEntry* _next; |
|
42 |
unsigned int _hash; |
|
33628 | 43 |
bool _latin1; |
23472 | 44 |
typeArrayOop _obj; |
45 |
||
46 |
public: |
|
47 |
G1StringDedupEntry() : |
|
48 |
_next(NULL), |
|
49 |
_hash(0), |
|
33628 | 50 |
_latin1(false), |
23472 | 51 |
_obj(NULL) { |
52 |
} |
|
53 |
||
54 |
G1StringDedupEntry* next() { |
|
55 |
return _next; |
|
56 |
} |
|
57 |
||
58 |
G1StringDedupEntry** next_addr() { |
|
59 |
return &_next; |
|
60 |
} |
|
61 |
||
62 |
void set_next(G1StringDedupEntry* next) { |
|
63 |
_next = next; |
|
64 |
} |
|
65 |
||
66 |
unsigned int hash() { |
|
67 |
return _hash; |
|
68 |
} |
|
69 |
||
70 |
void set_hash(unsigned int hash) { |
|
71 |
_hash = hash; |
|
72 |
} |
|
73 |
||
33628 | 74 |
bool latin1() { |
75 |
return _latin1; |
|
76 |
} |
|
77 |
||
78 |
void set_latin1(bool latin1) { |
|
79 |
_latin1 = latin1; |
|
80 |
} |
|
81 |
||
23472 | 82 |
typeArrayOop obj() { |
83 |
return _obj; |
|
84 |
} |
|
85 |
||
86 |
typeArrayOop* obj_addr() { |
|
87 |
return &_obj; |
|
88 |
} |
|
89 |
||
90 |
void set_obj(typeArrayOop obj) { |
|
91 |
_obj = obj; |
|
92 |
} |
|
93 |
}; |
|
94 |
||
95 |
// |
|
96 |
// The deduplication hashtable keeps track of all unique character arrays used |
|
97 |
// by String objects. Each table entry weakly points to an character array, allowing |
|
98 |
// otherwise unreachable character arrays to be declared dead and pruned from the |
|
99 |
// table. |
|
100 |
// |
|
101 |
// The table is dynamically resized to accommodate the current number of table entries. |
|
102 |
// The table has hash buckets with chains for hash collision. If the average chain |
|
103 |
// length goes above or below given thresholds the table grows or shrinks accordingly. |
|
104 |
// |
|
105 |
// The table is also dynamically rehashed (using a new hash seed) if it becomes severely |
|
106 |
// unbalanced, i.e., a hash chain is significantly longer than average. |
|
107 |
// |
|
108 |
// All access to the table is protected by the StringDedupTable_lock, except under |
|
109 |
// safepoints in which case GC workers are allowed to access a table partitions they |
|
110 |
// have claimed without first acquiring the lock. Note however, that this applies only |
|
111 |
// the table partition (i.e. a range of elements in _buckets), not other parts of the |
|
112 |
// table such as the _entries field, statistics counters, etc. |
|
113 |
// |
|
114 |
class G1StringDedupTable : public CHeapObj<mtGC> { |
|
115 |
private: |
|
116 |
// The currently active hashtable instance. Only modified when |
|
117 |
// the table is resizes or rehashed. |
|
118 |
static G1StringDedupTable* _table; |
|
119 |
||
120 |
// Cache for reuse and fast alloc/free of table entries. |
|
121 |
static G1StringDedupEntryCache* _entry_cache; |
|
122 |
||
123 |
G1StringDedupEntry** _buckets; |
|
124 |
size_t _size; |
|
125 |
uintx _entries; |
|
126 |
uintx _shrink_threshold; |
|
127 |
uintx _grow_threshold; |
|
128 |
bool _rehash_needed; |
|
129 |
||
130 |
// The hash seed also dictates which hash function to use. A |
|
131 |
// zero hash seed means we will use the Java compatible hash |
|
132 |
// function (which doesn't use a seed), and a non-zero hash |
|
133 |
// seed means we use the murmur3 hash function. |
|
134 |
jint _hash_seed; |
|
135 |
||
136 |
// Constants governing table resize/rehash/cache. |
|
137 |
static const size_t _min_size; |
|
138 |
static const size_t _max_size; |
|
139 |
static const double _grow_load_factor; |
|
140 |
static const double _shrink_load_factor; |
|
141 |
static const uintx _rehash_multiple; |
|
142 |
static const uintx _rehash_threshold; |
|
143 |
static const double _max_cache_factor; |
|
144 |
||
145 |
// Table statistics, only used for logging. |
|
146 |
static uintx _entries_added; |
|
147 |
static uintx _entries_removed; |
|
148 |
static uintx _resize_count; |
|
149 |
static uintx _rehash_count; |
|
150 |
||
151 |
G1StringDedupTable(size_t size, jint hash_seed = 0); |
|
152 |
~G1StringDedupTable(); |
|
153 |
||
154 |
// Returns the hash bucket at the given index. |
|
155 |
G1StringDedupEntry** bucket(size_t index) { |
|
156 |
return _buckets + index; |
|
157 |
} |
|
158 |
||
159 |
// Returns the hash bucket index for the given hash code. |
|
160 |
size_t hash_to_index(unsigned int hash) { |
|
161 |
return (size_t)hash & (_size - 1); |
|
162 |
} |
|
163 |
||
164 |
// Adds a new table entry to the given hash bucket. |
|
33628 | 165 |
void add(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list); |
23472 | 166 |
|
167 |
// Removes the given table entry from the table. |
|
168 |
void remove(G1StringDedupEntry** pentry, uint worker_id); |
|
169 |
||
170 |
// Transfers a table entry from the current table to the destination table. |
|
171 |
void transfer(G1StringDedupEntry** pentry, G1StringDedupTable* dest); |
|
172 |
||
173 |
// Returns an existing character array in the given hash bucket, or NULL |
|
174 |
// if no matching character array exists. |
|
33628 | 175 |
typeArrayOop lookup(typeArrayOop value, bool latin1, unsigned int hash, |
23472 | 176 |
G1StringDedupEntry** list, uintx &count); |
177 |
||
178 |
// Returns an existing character array in the table, or inserts a new |
|
179 |
// table entry if no matching character array exists. |
|
33628 | 180 |
typeArrayOop lookup_or_add_inner(typeArrayOop value, bool latin1, unsigned int hash); |
23472 | 181 |
|
182 |
// Thread safe lookup or add of table entry |
|
33628 | 183 |
static typeArrayOop lookup_or_add(typeArrayOop value, bool latin1, unsigned int hash) { |
23472 | 184 |
// Protect the table from concurrent access. Also note that this lock |
185 |
// acts as a fence for _table, which could have been replaced by a new |
|
186 |
// instance if the table was resized or rehashed. |
|
187 |
MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); |
|
33628 | 188 |
return _table->lookup_or_add_inner(value, latin1, hash); |
23472 | 189 |
} |
190 |
||
191 |
// Returns true if the hashtable is currently using a Java compatible |
|
192 |
// hash function. |
|
193 |
static bool use_java_hash() { |
|
194 |
return _table->_hash_seed == 0; |
|
195 |
} |
|
196 |
||
197 |
static bool equals(typeArrayOop value1, typeArrayOop value2); |
|
198 |
||
199 |
// Computes the hash code for the given character array, using the |
|
200 |
// currently active hash function and hash seed. |
|
33628 | 201 |
static unsigned int hash_code(typeArrayOop value, bool latin1); |
23472 | 202 |
|
203 |
static uintx unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, |
|
204 |
size_t partition_begin, |
|
205 |
size_t partition_end, |
|
206 |
uint worker_id); |
|
207 |
||
208 |
public: |
|
209 |
static void create(); |
|
210 |
||
211 |
// Deduplicates the given String object, or adds its backing |
|
212 |
// character array to the deduplication hashtable. |
|
213 |
static void deduplicate(oop java_string, G1StringDedupStat& stat); |
|
214 |
||
215 |
// If a table resize is needed, returns a newly allocated empty |
|
216 |
// hashtable of the proper size. |
|
217 |
static G1StringDedupTable* prepare_resize(); |
|
218 |
||
219 |
// Installs a newly resized table as the currently active table |
|
220 |
// and deletes the previously active table. |
|
221 |
static void finish_resize(G1StringDedupTable* resized_table); |
|
222 |
||
223 |
// If a table rehash is needed, returns a newly allocated empty |
|
224 |
// hashtable and updates the hash seed. |
|
225 |
static G1StringDedupTable* prepare_rehash(); |
|
226 |
||
227 |
// Transfers rehashed entries from the currently active table into |
|
228 |
// the new table. Installs the new table as the currently active table |
|
229 |
// and deletes the previously active table. |
|
230 |
static void finish_rehash(G1StringDedupTable* rehashed_table); |
|
231 |
||
39452
eebe070746ad
8158871: Long response times with G1 and StringDeduplication
pliden
parents:
35061
diff
changeset
|
232 |
// If the table entry cache has grown too large, delete overflowed entries. |
eebe070746ad
8158871: Long response times with G1 and StringDeduplication
pliden
parents:
35061
diff
changeset
|
233 |
static void clean_entry_cache(); |
23472 | 234 |
|
235 |
static void unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl, uint worker_id); |
|
236 |
||
35061 | 237 |
static void print_statistics(); |
23472 | 238 |
static void verify(); |
239 |
}; |
|
240 |
||
30764 | 241 |
#endif // SHARE_VM_GC_G1_G1STRINGDEDUPTABLE_HPP |