Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
16670578
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
16670578
编写于
6月 30, 2016
作者:
V
vkempik
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8158871: Long response times with G1 and StringDeduplication
Reviewed-by: pliden, tschatzl
上级
e1b27304
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
83 addition
and
41 deletion
+83
-41
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
+78
-36
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
+3
-3
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
+2
-2
未找到文件。
src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp
浏览文件 @
16670578
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014,
2016,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -28,22 +28,23 @@
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/g1StringDedupTable.hpp"
#include "gc_implementation/shared/concurrentGCThread.hpp"
#include "memory/gcLocker.hpp"
#include "memory/padded.inline.hpp"
#include "oops/typeArrayOop.hpp"
#include "runtime/mutexLocker.hpp"
//
//
Freelist in the deduplication table entry cache
. Links table
//
List of deduplication table entries
. Links table
// entries together using their _next fields.
//
class
G1StringDedupEntry
Free
List
:
public
CHeapObj
<
mtGC
>
{
class
G1StringDedupEntryList
:
public
CHeapObj
<
mtGC
>
{
private:
G1StringDedupEntry
*
_list
;
size_t
_length
;
public:
G1StringDedupEntry
Free
List
()
:
G1StringDedupEntryList
()
:
_list
(
NULL
),
_length
(
0
)
{
}
...
...
@@ -63,6 +64,12 @@ public:
return
entry
;
}
G1StringDedupEntry
*
remove_all
()
{
G1StringDedupEntry
*
list
=
_list
;
_list
=
NULL
;
return
list
;
}
size_t
length
()
{
return
_length
;
}
...
...
@@ -84,43 +91,53 @@ public:
//
class
G1StringDedupEntryCache
:
public
CHeapObj
<
mtGC
>
{
private:
// One freelist per GC worker to allow lock less freeing of
// entries while doing a parallel scan of the table. Using
// PaddedEnd to avoid false sharing.
PaddedEnd
<
G1StringDedupEntryFreeList
>*
_lists
;
// One cache/overflow list per GC worker to allow lock less freeing of
// entries while doing a parallel scan of the table. Using PaddedEnd to
// avoid false sharing.
size_t
_nlists
;
size_t
_max_list_length
;
PaddedEnd
<
G1StringDedupEntryList
>*
_cached
;
PaddedEnd
<
G1StringDedupEntryList
>*
_overflowed
;
public:
G1StringDedupEntryCache
();
G1StringDedupEntryCache
(
size_t
max_size
);
~
G1StringDedupEntryCache
();
// Get a table entry from the cache freelist, or allocate a new
// entry if the cache is empty.
// Set max number of table entries to cache.
void
set_max_size
(
size_t
max_size
);
// Get a table entry from the cache, or allocate a new entry if the cache is empty.
G1StringDedupEntry
*
alloc
();
// Insert a table entry into the cache
freelist
.
// Insert a table entry into the cache.
void
free
(
G1StringDedupEntry
*
entry
,
uint
worker_id
);
// Returns current number of entries in the cache.
size_t
size
();
// If the cache has grown above the given max size, trim it down
// and deallocate the memory occupied by trimmed of entries.
void
trim
(
size_t
max_size
);
// Deletes overflowed entries.
void
delete_overflowed
();
};
G1StringDedupEntryCache
::
G1StringDedupEntryCache
()
{
_nlists
=
MAX2
(
ParallelGCThreads
,
(
size_t
)
1
);
_lists
=
PaddedArray
<
G1StringDedupEntryFreeList
,
mtGC
>::
create_unfreeable
((
uint
)
_nlists
);
G1StringDedupEntryCache
::
G1StringDedupEntryCache
(
size_t
max_size
)
:
_nlists
(
MAX2
(
ParallelGCThreads
,
(
size_t
)
1
)),
_max_list_length
(
0
),
_cached
(
PaddedArray
<
G1StringDedupEntryList
,
mtGC
>::
create_unfreeable
((
uint
)
_nlists
)),
_overflowed
(
PaddedArray
<
G1StringDedupEntryList
,
mtGC
>::
create_unfreeable
((
uint
)
_nlists
))
{
set_max_size
(
max_size
);
}
G1StringDedupEntryCache
::~
G1StringDedupEntryCache
()
{
ShouldNotReachHere
();
}
void
G1StringDedupEntryCache
::
set_max_size
(
size_t
size
)
{
_max_list_length
=
size
/
_nlists
;
}
G1StringDedupEntry
*
G1StringDedupEntryCache
::
alloc
()
{
for
(
size_t
i
=
0
;
i
<
_nlists
;
i
++
)
{
G1StringDedupEntry
*
entry
=
_
lists
[
i
].
remove
();
G1StringDedupEntry
*
entry
=
_
cached
[
i
].
remove
();
if
(
entry
!=
NULL
)
{
return
entry
;
}
...
...
@@ -131,31 +148,55 @@ G1StringDedupEntry* G1StringDedupEntryCache::alloc() {
void
G1StringDedupEntryCache
::
free
(
G1StringDedupEntry
*
entry
,
uint
worker_id
)
{
assert
(
entry
->
obj
()
!=
NULL
,
"Double free"
);
assert
(
worker_id
<
_nlists
,
"Invalid worker id"
);
entry
->
set_obj
(
NULL
);
entry
->
set_hash
(
0
);
_lists
[
worker_id
].
add
(
entry
);
if
(
_cached
[
worker_id
].
length
()
<
_max_list_length
)
{
// Cache is not full
_cached
[
worker_id
].
add
(
entry
);
}
else
{
// Cache is full, add to overflow list for later deletion
_overflowed
[
worker_id
].
add
(
entry
);
}
}
size_t
G1StringDedupEntryCache
::
size
()
{
size_t
size
=
0
;
for
(
size_t
i
=
0
;
i
<
_nlists
;
i
++
)
{
size
+=
_
lists
[
i
].
length
();
size
+=
_
cached
[
i
].
length
();
}
return
size
;
}
void
G1StringDedupEntryCache
::
trim
(
size_t
max_size
)
{
size_t
cache_size
=
0
;
void
G1StringDedupEntryCache
::
delete_overflowed
()
{
double
start
=
os
::
elapsedTime
();
uintx
count
=
0
;
for
(
size_t
i
=
0
;
i
<
_nlists
;
i
++
)
{
G1StringDedupEntryFreeList
*
list
=
&
_lists
[
i
];
cache_size
+=
list
->
length
();
while
(
cache_size
>
max_size
)
{
G1StringDedupEntry
*
entry
=
list
->
remove
();
assert
(
entry
!=
NULL
,
"Should not be null"
);
cache_size
--
;
G1StringDedupEntry
*
entry
;
{
// The overflow list can be modified during safepoints, therefore
// we temporarily join the suspendible thread set while removing
// all entries from the list.
SuspendibleThreadSetJoiner
sts_join
;
entry
=
_overflowed
[
i
].
remove_all
();
}
// Delete all entries
while
(
entry
!=
NULL
)
{
G1StringDedupEntry
*
next
=
entry
->
next
();
delete
entry
;
entry
=
next
;
count
++
;
}
}
double
end
=
os
::
elapsedTime
();
if
(
PrintStringDeduplicationStatistics
)
{
gclog_or_tty
->
print_cr
(
"[GC concurrent-string-deduplication, deleted "
UINTX_FORMAT
" entries, "
G1_STRDEDUP_TIME_FORMAT
"]"
,
count
,
end
-
start
);
}
}
G1StringDedupTable
*
G1StringDedupTable
::
_table
=
NULL
;
...
...
@@ -192,7 +233,7 @@ G1StringDedupTable::~G1StringDedupTable() {
void
G1StringDedupTable
::
create
()
{
assert
(
_table
==
NULL
,
"One string deduplication table allowed"
);
_entry_cache
=
new
G1StringDedupEntryCache
();
_entry_cache
=
new
G1StringDedupEntryCache
(
(
size_t
)(
_min_size
*
_max_cache_factor
)
);
_table
=
new
G1StringDedupTable
(
_min_size
);
}
...
...
@@ -375,6 +416,9 @@ G1StringDedupTable* G1StringDedupTable::prepare_resize() {
// Update statistics
_resize_count
++
;
// Update max cache size
_entry_cache
->
set_max_size
((
size_t
)(
size
*
_max_cache_factor
));
// Allocate the new table. The new table will be populated by workers
// calling unlink_or_oops_do() and finally installed by finish_resize().
return
new
G1StringDedupTable
(
size
,
_table
->
_hash_seed
);
...
...
@@ -427,7 +471,7 @@ void G1StringDedupTable::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* c
removed
+=
unlink_or_oops_do
(
cl
,
table_half
+
partition_begin
,
table_half
+
partition_end
,
worker_id
);
}
// Delayed update avoid contention on the table lock
// Delayed update
to
avoid contention on the table lock
if
(
removed
>
0
)
{
MutexLockerEx
ml
(
StringDedupTable_lock
,
Mutex
::
_no_safepoint_check_flag
);
_table
->
_entries
-=
removed
;
...
...
@@ -545,10 +589,8 @@ void G1StringDedupTable::verify() {
}
}
void
G1StringDedupTable
::
trim_entry_cache
()
{
MutexLockerEx
ml
(
StringDedupTable_lock
,
Mutex
::
_no_safepoint_check_flag
);
size_t
max_cache_size
=
(
size_t
)(
_table
->
_size
*
_max_cache_factor
);
_entry_cache
->
trim
(
max_cache_size
);
void
G1StringDedupTable
::
clean_entry_cache
()
{
_entry_cache
->
delete_overflowed
();
}
void
G1StringDedupTable
::
print_statistics
(
outputStream
*
st
)
{
...
...
src/share/vm/gc_implementation/g1/g1StringDedupTable.hpp
浏览文件 @
16670578
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014,
2016,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -218,8 +218,8 @@ public:
// and deletes the previously active table.
static
void
finish_rehash
(
G1StringDedupTable
*
rehashed_table
);
// If the table entry cache has grown too large,
trim it down according to policy
static
void
trim
_entry_cache
();
// If the table entry cache has grown too large,
delete overflowed entries.
static
void
clean
_entry_cache
();
static
void
unlink_or_oops_do
(
G1StringDedupUnlinkOrOopsDoClosure
*
cl
,
uint
worker_id
);
...
...
src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
浏览文件 @
16670578
...
...
@@ -100,14 +100,14 @@ void G1StringDedupThread::run() {
}
}
G1StringDedupTable
::
trim_entry_cache
();
stat
.
mark_done
();
// Print statistics
total_stat
.
add
(
stat
);
print
(
gclog_or_tty
,
stat
,
total_stat
);
}
G1StringDedupTable
::
clean_entry_cache
();
}
terminate
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录