Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
1de115b4
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看板
提交
1de115b4
编写于
7月 06, 2018
作者:
P
poonam
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8146115: Improve docker container detection and resource configuration usage
Reviewed-by: bobv, dbuck
上级
47268b75
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
1113 addition
and
105 deletion
+1113
-105
src/os/aix/vm/os_aix.cpp
src/os/aix/vm/os_aix.cpp
+10
-0
src/os/bsd/vm/os_bsd.cpp
src/os/bsd/vm/os_bsd.cpp
+10
-0
src/os/linux/vm/globals_linux.hpp
src/os/linux/vm/globals_linux.hpp
+8
-3
src/os/linux/vm/osContainer_linux.cpp
src/os/linux/vm/osContainer_linux.cpp
+680
-0
src/os/linux/vm/osContainer_linux.hpp
src/os/linux/vm/osContainer_linux.hpp
+68
-0
src/os/linux/vm/os_linux.cpp
src/os/linux/vm/os_linux.cpp
+150
-5
src/os/linux/vm/os_linux.hpp
src/os/linux/vm/os_linux.hpp
+5
-0
src/os/solaris/vm/os_solaris.cpp
src/os/solaris/vm/os_solaris.cpp
+10
-0
src/os/windows/vm/os_windows.cpp
src/os/windows/vm/os_windows.cpp
+10
-0
src/share/vm/runtime/arguments.cpp
src/share/vm/runtime/arguments.cpp
+125
-94
src/share/vm/runtime/arguments.hpp
src/share/vm/runtime/arguments.hpp
+3
-1
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+25
-2
src/share/vm/runtime/os.hpp
src/share/vm/runtime/os.hpp
+8
-0
src/share/vm/runtime/thread.cpp
src/share/vm/runtime/thread.cpp
+1
-0
未找到文件。
src/os/aix/vm/os_aix.cpp
浏览文件 @
1de115b4
...
...
@@ -4008,6 +4008,16 @@ void os::make_polling_page_readable(void) {
};
int
os
::
active_processor_count
()
{
// User has overridden the number of active processors
if
(
ActiveProcessorCount
>
0
)
{
if
(
PrintActiveCpus
)
{
tty
->
print_cr
(
"active_processor_count: "
"active processor count set by user : %d"
,
ActiveProcessorCount
);
}
return
ActiveProcessorCount
;
}
int
online_cpus
=
::
sysconf
(
_SC_NPROCESSORS_ONLN
);
assert
(
online_cpus
>
0
&&
online_cpus
<=
processor_count
(),
"sanity check"
);
return
online_cpus
;
...
...
src/os/bsd/vm/os_bsd.cpp
浏览文件 @
1de115b4
...
...
@@ -3765,6 +3765,16 @@ void os::make_polling_page_readable(void) {
};
int
os
::
active_processor_count
()
{
// User has overridden the number of active processors
if
(
ActiveProcessorCount
>
0
)
{
if
(
PrintActiveCpus
)
{
tty
->
print_cr
(
"active_processor_count: "
"active processor count set by user : %d"
,
ActiveProcessorCount
);
}
return
ActiveProcessorCount
;
}
return
_processor_count
;
}
...
...
src/os/linux/vm/globals_linux.hpp
浏览文件 @
1de115b4
/*
* Copyright (c) 2005, 201
6
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 201
8
, 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
...
...
@@ -49,8 +49,13 @@
product(bool, UseSHM, false, \
"Use SYSV shared memory for large pages") \
\
diagnostic(bool, PrintActiveCpus, false, \
"Print the number of CPUs detected in os::active_processor_count")
product(bool, UseContainerSupport, true, \
"Enable detection and runtime container configuration support") \
\
product(bool, PreferContainerQuotaForCPUCount, true, \
"Calculate the container CPU availability based on the value" \
" of quotas (if set), when true. Otherwise, use the CPU" \
" shares value, provided it is less than quota.")
//
// Defines Linux-specific default values. The flags are available on all
...
...
src/os/linux/vm/osContainer_linux.cpp
0 → 100644
浏览文件 @
1de115b4
/*
* Copyright (c) 2017, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <string.h>
#include <math.h>
#include <errno.h>
#include "utilities/globalDefinitions.hpp"
#include "memory/allocation.hpp"
#include "runtime/os.hpp"
#include "osContainer_linux.hpp"
#define PER_CPU_SHARES 1024
bool
OSContainer
::
_is_initialized
=
false
;
bool
OSContainer
::
_is_containerized
=
false
;
julong
_unlimited_memory
;
class
CgroupSubsystem
:
CHeapObj
<
mtInternal
>
{
friend
class
OSContainer
;
private:
/* mountinfo contents */
char
*
_root
;
char
*
_mount_point
;
/* Constructed subsystem directory */
char
*
_path
;
public:
CgroupSubsystem
(
char
*
root
,
char
*
mountpoint
)
{
_root
=
os
::
strdup
(
root
);
_mount_point
=
os
::
strdup
(
mountpoint
);
_path
=
NULL
;
}
/*
* Set directory to subsystem specific files based
* on the contents of the mountinfo and cgroup files.
*/
void
set_subsystem_path
(
char
*
cgroup_path
)
{
char
buf
[
MAXPATHLEN
+
1
];
if
(
_root
!=
NULL
&&
cgroup_path
!=
NULL
)
{
if
(
strcmp
(
_root
,
"/"
)
==
0
)
{
int
buflen
;
strncpy
(
buf
,
_mount_point
,
MAXPATHLEN
);
buf
[
MAXPATHLEN
-
1
]
=
'\0'
;
if
(
strcmp
(
cgroup_path
,
"/"
)
!=
0
)
{
buflen
=
strlen
(
buf
);
if
((
buflen
+
strlen
(
cgroup_path
))
>
(
MAXPATHLEN
-
1
))
{
return
;
}
strncat
(
buf
,
cgroup_path
,
MAXPATHLEN
-
buflen
);
buf
[
MAXPATHLEN
-
1
]
=
'\0'
;
}
_path
=
os
::
strdup
(
buf
);
}
else
{
if
(
strcmp
(
_root
,
cgroup_path
)
==
0
)
{
strncpy
(
buf
,
_mount_point
,
MAXPATHLEN
);
buf
[
MAXPATHLEN
-
1
]
=
'\0'
;
_path
=
os
::
strdup
(
buf
);
}
else
{
char
*
p
=
strstr
(
_root
,
cgroup_path
);
if
(
p
!=
NULL
&&
p
==
_root
)
{
if
(
strlen
(
cgroup_path
)
>
strlen
(
_root
))
{
int
buflen
;
strncpy
(
buf
,
_mount_point
,
MAXPATHLEN
);
buf
[
MAXPATHLEN
-
1
]
=
'\0'
;
buflen
=
strlen
(
buf
);
if
((
buflen
+
strlen
(
cgroup_path
))
>
(
MAXPATHLEN
-
1
))
{
return
;
}
strncat
(
buf
,
cgroup_path
+
strlen
(
_root
),
MAXPATHLEN
-
buflen
);
buf
[
MAXPATHLEN
-
1
]
=
'\0'
;
_path
=
os
::
strdup
(
buf
);
}
}
}
}
}
}
char
*
subsystem_path
()
{
return
_path
;
}
};
CgroupSubsystem
*
memory
=
NULL
;
CgroupSubsystem
*
cpuset
=
NULL
;
CgroupSubsystem
*
cpu
=
NULL
;
CgroupSubsystem
*
cpuacct
=
NULL
;
typedef
char
*
cptr
;
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED
template
<
typename
T
>
int
subsystem_file_contents
(
CgroupSubsystem
*
c
,
const
char
*
filename
,
const
char
*
scan_fmt
,
T
returnval
)
{
FILE
*
fp
=
NULL
;
char
*
p
;
char
file
[
MAXPATHLEN
+
1
];
char
buf
[
MAXPATHLEN
+
1
];
if
(
c
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"subsystem_file_contents: CgroupSubsytem* is NULL"
);
}
return
OSCONTAINER_ERROR
;
}
if
(
c
->
subsystem_path
()
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"subsystem_file_contents: subsystem path is NULL"
);
}
return
OSCONTAINER_ERROR
;
}
strncpy
(
file
,
c
->
subsystem_path
(),
MAXPATHLEN
);
file
[
MAXPATHLEN
-
1
]
=
'\0'
;
int
filelen
=
strlen
(
file
);
if
((
filelen
+
strlen
(
filename
))
>
(
MAXPATHLEN
-
1
))
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"File path too long %s, %s"
,
file
,
filename
);
}
return
OSCONTAINER_ERROR
;
}
strncat
(
file
,
filename
,
MAXPATHLEN
-
filelen
);
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Path to %s is %s"
,
filename
,
file
);
}
fp
=
fopen
(
file
,
"r"
);
if
(
fp
!=
NULL
)
{
p
=
fgets
(
buf
,
MAXPATHLEN
,
fp
);
if
(
p
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
scan_fmt
,
returnval
);
if
(
matched
==
1
)
{
fclose
(
fp
);
return
0
;
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Type %s not found in file %s"
,
scan_fmt
,
file
);
}
}
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Empty file %s"
,
file
);
}
}
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Open of file %s failed, %s"
,
file
,
strerror
(
errno
));
}
}
if
(
fp
!=
NULL
)
fclose
(
fp
);
return
OSCONTAINER_ERROR
;
}
PRAGMA_DIAG_POP
#define GET_CONTAINER_INFO(return_type, subsystem, filename, \
logstring, scan_fmt, variable) \
return_type variable; \
{ \
int err; \
err = subsystem_file_contents(subsystem, \
filename, \
scan_fmt, \
&variable); \
if (err != 0) \
return (return_type) OSCONTAINER_ERROR; \
\
if (PrintContainerInfo) \
tty->print_cr(logstring, variable); \
}
#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \
logstring, scan_fmt, variable, bufsize) \
char variable[bufsize]; \
{ \
int err; \
err = subsystem_file_contents(subsystem, \
filename, \
scan_fmt, \
variable); \
if (err != 0) \
return (return_type) NULL; \
\
if (PrintContainerInfo) \
tty->print_cr(logstring, variable); \
}
/* init
*
* Initialize the container support and determine if
* we are running under cgroup control.
*/
void
OSContainer
::
init
()
{
int
mountid
;
int
parentid
;
int
major
;
int
minor
;
FILE
*
mntinfo
=
NULL
;
FILE
*
cgroup
=
NULL
;
char
buf
[
MAXPATHLEN
+
1
];
char
tmproot
[
MAXPATHLEN
+
1
];
char
tmpmount
[
MAXPATHLEN
+
1
];
char
tmpbase
[
MAXPATHLEN
+
1
];
char
*
p
;
jlong
mem_limit
;
assert
(
!
_is_initialized
,
"Initializing OSContainer more than once"
);
_is_initialized
=
true
;
_is_containerized
=
false
;
_unlimited_memory
=
(
LONG_MAX
/
os
::
vm_page_size
())
*
os
::
vm_page_size
();
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"OSContainer::init: Initializing Container Support"
);
}
if
(
!
UseContainerSupport
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Container Support not enabled"
);
}
return
;
}
/*
* Find the cgroup mount point for memory and cpuset
* by reading /proc/self/mountinfo
*
* Example for docker:
* 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
*
* Example for host:
* 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory
*/
mntinfo
=
fopen
(
"/proc/self/mountinfo"
,
"r"
);
if
(
mntinfo
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Can't open /proc/self/mountinfo, %s"
,
strerror
(
errno
));
}
return
;
}
while
(
(
p
=
fgets
(
buf
,
MAXPATHLEN
,
mntinfo
))
!=
NULL
)
{
// Look for the filesystem type and see if it's cgroup
char
fstype
[
MAXPATHLEN
+
1
];
fstype
[
0
]
=
'\0'
;
char
*
s
=
strstr
(
p
,
" - "
);
if
(
s
!=
NULL
&&
sscanf
(
s
,
" - %s"
,
fstype
)
==
1
&&
strcmp
(
fstype
,
"cgroup"
)
==
0
)
{
if
(
strstr
(
p
,
"memory"
)
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
"%d %d %d:%d %s %s"
,
&
mountid
,
&
parentid
,
&
major
,
&
minor
,
tmproot
,
tmpmount
);
if
(
matched
==
6
)
{
memory
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
}
else
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Incompatible str containing cgroup and memory: %s"
,
p
);
}
}
else
if
(
strstr
(
p
,
"cpuset"
)
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
"%d %d %d:%d %s %s"
,
&
mountid
,
&
parentid
,
&
major
,
&
minor
,
tmproot
,
tmpmount
);
if
(
matched
==
6
)
{
cpuset
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Incompatible str containing cgroup and cpuset: %s"
,
p
);
}
}
}
else
if
(
strstr
(
p
,
"cpu,cpuacct"
)
!=
NULL
||
strstr
(
p
,
"cpuacct,cpu"
)
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
"%d %d %d:%d %s %s"
,
&
mountid
,
&
parentid
,
&
major
,
&
minor
,
tmproot
,
tmpmount
);
if
(
matched
==
6
)
{
cpu
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
cpuacct
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Incompatible str containing cgroup and cpu,cpuacct: %s"
,
p
);
}
}
}
else
if
(
strstr
(
p
,
"cpuacct"
)
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
"%d %d %d:%d %s %s"
,
&
mountid
,
&
parentid
,
&
major
,
&
minor
,
tmproot
,
tmpmount
);
if
(
matched
==
6
)
{
cpuacct
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Incompatible str containing cgroup and cpuacct: %s"
,
p
);
}
}
}
else
if
(
strstr
(
p
,
"cpu"
)
!=
NULL
)
{
int
matched
=
sscanf
(
p
,
"%d %d %d:%d %s %s"
,
&
mountid
,
&
parentid
,
&
major
,
&
minor
,
tmproot
,
tmpmount
);
if
(
matched
==
6
)
{
cpu
=
new
CgroupSubsystem
(
tmproot
,
tmpmount
);
}
else
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Incompatible str containing cgroup and cpu: %s"
,
p
);
}
}
}
}
}
fclose
(
mntinfo
);
if
(
memory
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Required cgroup memory subsystem not found"
);
}
return
;
}
if
(
cpuset
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Required cgroup cpuset subsystem not found"
);
}
return
;
}
if
(
cpu
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Required cgroup cpu subsystem not found"
);
}
return
;
}
if
(
cpuacct
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Required cgroup cpuacct subsystem not found"
);
}
return
;
}
/*
* Read /proc/self/cgroup and map host mount point to
* local one via /proc/self/mountinfo content above
*
* Docker example:
* 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
*
* Host example:
* 5:memory:/user.slice
*
* Construct a path to the process specific memory and cpuset
* cgroup directory.
*
* For a container running under Docker from memory example above
* the paths would be:
*
* /sys/fs/cgroup/memory
*
* For a Host from memory example above the path would be:
*
* /sys/fs/cgroup/memory/user.slice
*
*/
cgroup
=
fopen
(
"/proc/self/cgroup"
,
"r"
);
if
(
cgroup
==
NULL
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Can't open /proc/self/cgroup, %s"
,
strerror
(
errno
));
}
return
;
}
while
(
(
p
=
fgets
(
buf
,
MAXPATHLEN
,
cgroup
))
!=
NULL
)
{
int
cgno
;
int
matched
;
char
*
controller
;
char
*
base
;
/* Skip cgroup number */
strsep
(
&
p
,
":"
);
/* Get controller and base */
controller
=
strsep
(
&
p
,
":"
);
base
=
strsep
(
&
p
,
"
\n
"
);
if
(
controller
!=
NULL
)
{
if
(
strstr
(
controller
,
"memory"
)
!=
NULL
)
{
memory
->
set_subsystem_path
(
base
);
}
else
if
(
strstr
(
controller
,
"cpuset"
)
!=
NULL
)
{
cpuset
->
set_subsystem_path
(
base
);
}
else
if
(
strstr
(
controller
,
"cpu,cpuacct"
)
!=
NULL
||
strstr
(
controller
,
"cpuacct,cpu"
)
!=
NULL
)
{
cpu
->
set_subsystem_path
(
base
);
cpuacct
->
set_subsystem_path
(
base
);
}
else
if
(
strstr
(
controller
,
"cpuacct"
)
!=
NULL
)
{
cpuacct
->
set_subsystem_path
(
base
);
}
else
if
(
strstr
(
controller
,
"cpu"
)
!=
NULL
)
{
cpu
->
set_subsystem_path
(
base
);
}
}
}
fclose
(
cgroup
);
// We need to update the amount of physical memory now that
// command line arguments have been processed.
if
((
mem_limit
=
memory_limit_in_bytes
())
>
0
)
{
os
::
Linux
::
set_physical_memory
(
mem_limit
);
}
_is_containerized
=
true
;
}
const
char
*
OSContainer
::
container_type
()
{
if
(
is_containerized
())
{
return
"cgroupv1"
;
}
else
{
return
NULL
;
}
}
/* memory_limit_in_bytes
*
* Return the limit of available memory for this process.
*
* return:
* memory limit in bytes or
* -1 for unlimited
* OSCONTAINER_ERROR for not supported
*/
jlong
OSContainer
::
memory_limit_in_bytes
()
{
GET_CONTAINER_INFO
(
julong
,
memory
,
"/memory.limit_in_bytes"
,
"Memory Limit is: "
JULONG_FORMAT
,
JULONG_FORMAT
,
memlimit
);
if
(
memlimit
>=
_unlimited_memory
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Memory Limit is: Unlimited"
);
}
return
(
jlong
)
-
1
;
}
else
{
return
(
jlong
)
memlimit
;
}
}
jlong
OSContainer
::
memory_and_swap_limit_in_bytes
()
{
GET_CONTAINER_INFO
(
julong
,
memory
,
"/memory.memsw.limit_in_bytes"
,
"Memory and Swap Limit is: "
JULONG_FORMAT
,
JULONG_FORMAT
,
memswlimit
);
if
(
memswlimit
>=
_unlimited_memory
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Memory and Swap Limit is: Unlimited"
);
}
return
(
jlong
)
-
1
;
}
else
{
return
(
jlong
)
memswlimit
;
}
}
jlong
OSContainer
::
memory_soft_limit_in_bytes
()
{
GET_CONTAINER_INFO
(
julong
,
memory
,
"/memory.soft_limit_in_bytes"
,
"Memory Soft Limit is: "
JULONG_FORMAT
,
JULONG_FORMAT
,
memsoftlimit
);
if
(
memsoftlimit
>=
_unlimited_memory
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"Memory Soft Limit is: Unlimited"
);
}
return
(
jlong
)
-
1
;
}
else
{
return
(
jlong
)
memsoftlimit
;
}
}
/* memory_usage_in_bytes
*
* Return the amount of used memory for this process.
*
* return:
* memory usage in bytes or
* -1 for unlimited
* OSCONTAINER_ERROR for not supported
*/
jlong
OSContainer
::
memory_usage_in_bytes
()
{
GET_CONTAINER_INFO
(
jlong
,
memory
,
"/memory.usage_in_bytes"
,
"Memory Usage is: "
JLONG_FORMAT
,
JLONG_FORMAT
,
memusage
);
return
memusage
;
}
/* memory_max_usage_in_bytes
*
* Return the maximum amount of used memory for this process.
*
* return:
* max memory usage in bytes or
* OSCONTAINER_ERROR for not supported
*/
jlong
OSContainer
::
memory_max_usage_in_bytes
()
{
GET_CONTAINER_INFO
(
jlong
,
memory
,
"/memory.max_usage_in_bytes"
,
"Maximum Memory Usage is: "
JLONG_FORMAT
,
JLONG_FORMAT
,
memmaxusage
);
return
memmaxusage
;
}
/* active_processor_count
*
* Calculate an appropriate number of active processors for the
* VM to use based on these three inputs.
*
* cpu affinity
* cgroup cpu quota & cpu period
* cgroup cpu shares
*
* Algorithm:
*
* Determine the number of available CPUs from sched_getaffinity
*
* If user specified a quota (quota != -1), calculate the number of
* required CPUs by dividing quota by period.
*
* If shares are in effect (shares != -1), calculate the number
* of CPUs required for the shares by dividing the share value
* by PER_CPU_SHARES.
*
* All results of division are rounded up to the next whole number.
*
* If neither shares or quotas have been specified, return the
* number of active processors in the system.
*
* If both shares and quotas have been specified, the results are
* based on the flag PreferContainerQuotaForCPUCount. If true,
* return the quota value. If false return the smallest value
* between shares or quotas.
*
* If shares and/or quotas have been specified, the resulting number
* returned will never exceed the number of active processors.
*
* return:
* number of CPUs
*/
int
OSContainer
::
active_processor_count
()
{
int
quota_count
=
0
,
share_count
=
0
;
int
cpu_count
,
limit_count
;
int
result
;
cpu_count
=
limit_count
=
os
::
Linux
::
active_processor_count
();
int
quota
=
cpu_quota
();
int
period
=
cpu_period
();
int
share
=
cpu_shares
();
if
(
quota
>
-
1
&&
period
>
0
)
{
quota_count
=
ceilf
((
float
)
quota
/
(
float
)
period
);
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"CPU Quota count based on quota/period: %d"
,
quota_count
);
}
}
if
(
share
>
-
1
)
{
share_count
=
ceilf
((
float
)
share
/
(
float
)
PER_CPU_SHARES
);
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"CPU Share count based on shares: %d"
,
share_count
);
}
}
// If both shares and quotas are setup results depend
// on flag PreferContainerQuotaForCPUCount.
// If true, limit CPU count to quota
// If false, use minimum of shares and quotas
if
(
quota_count
!=
0
&&
share_count
!=
0
)
{
if
(
PreferContainerQuotaForCPUCount
)
{
limit_count
=
quota_count
;
}
else
{
limit_count
=
MIN2
(
quota_count
,
share_count
);
}
}
else
if
(
quota_count
!=
0
)
{
limit_count
=
quota_count
;
}
else
if
(
share_count
!=
0
)
{
limit_count
=
share_count
;
}
result
=
MIN2
(
cpu_count
,
limit_count
);
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"OSContainer::active_processor_count: %d"
,
result
);
}
return
result
;
}
char
*
OSContainer
::
cpu_cpuset_cpus
()
{
GET_CONTAINER_INFO_CPTR
(
cptr
,
cpuset
,
"/cpuset.cpus"
,
"cpuset.cpus is: %s"
,
"%1023s"
,
cpus
,
1024
);
return
os
::
strdup
(
cpus
);
}
char
*
OSContainer
::
cpu_cpuset_memory_nodes
()
{
GET_CONTAINER_INFO_CPTR
(
cptr
,
cpuset
,
"/cpuset.mems"
,
"cpuset.mems is: %s"
,
"%1023s"
,
mems
,
1024
);
return
os
::
strdup
(
mems
);
}
/* cpu_quota
*
* Return the number of milliseconds per period
* process is guaranteed to run.
*
* return:
* quota time in milliseconds
* -1 for no quota
* OSCONTAINER_ERROR for not supported
*/
int
OSContainer
::
cpu_quota
()
{
GET_CONTAINER_INFO
(
int
,
cpu
,
"/cpu.cfs_quota_us"
,
"CPU Quota is: %d"
,
"%d"
,
quota
);
return
quota
;
}
int
OSContainer
::
cpu_period
()
{
GET_CONTAINER_INFO
(
int
,
cpu
,
"/cpu.cfs_period_us"
,
"CPU Period is: %d"
,
"%d"
,
period
);
return
period
;
}
/* cpu_shares
*
* Return the amount of cpu shares available to the process
*
* return:
* Share number (typically a number relative to 1024)
* (2048 typically expresses 2 CPUs worth of processing)
* -1 for no share setup
* OSCONTAINER_ERROR for not supported
*/
int
OSContainer
::
cpu_shares
()
{
GET_CONTAINER_INFO
(
int
,
cpu
,
"/cpu.shares"
,
"CPU Shares is: %d"
,
"%d"
,
shares
);
// Convert 1024 to no shares setup
if
(
shares
==
1024
)
return
-
1
;
return
shares
;
}
src/os/linux/vm/osContainer_linux.hpp
0 → 100644
浏览文件 @
1de115b4
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_LINUX_VM_OSCONTAINER_LINUX_HPP
#define OS_LINUX_VM_OSCONTAINER_LINUX_HPP
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "memory/allocation.hpp"
#define OSCONTAINER_ERROR (-2)
class
OSContainer
:
AllStatic
{
private:
static
bool
_is_initialized
;
static
bool
_is_containerized
;
public:
static
void
init
();
static
inline
bool
is_containerized
();
static
const
char
*
container_type
();
static
jlong
memory_limit_in_bytes
();
static
jlong
memory_and_swap_limit_in_bytes
();
static
jlong
memory_soft_limit_in_bytes
();
static
jlong
memory_usage_in_bytes
();
static
jlong
memory_max_usage_in_bytes
();
static
int
active_processor_count
();
static
char
*
cpu_cpuset_cpus
();
static
char
*
cpu_cpuset_memory_nodes
();
static
int
cpu_quota
();
static
int
cpu_period
();
static
int
cpu_shares
();
};
inline
bool
OSContainer
::
is_containerized
()
{
assert
(
_is_initialized
,
"OSContainer not initialized"
);
return
_is_containerized
;
}
#endif // OS_LINUX_VM_OSCONTAINER_LINUX_HPP
src/os/linux/vm/os_linux.cpp
浏览文件 @
1de115b4
...
...
@@ -37,6 +37,7 @@
#include "mutex_linux.inline.hpp"
#include "oops/oop.inline.hpp"
#include "os_share_linux.hpp"
#include "osContainer_linux.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
...
...
@@ -179,13 +180,62 @@ julong os::available_memory() {
julong
os
::
Linux
::
available_memory
()
{
// values in struct sysinfo are "unsigned long"
struct
sysinfo
si
;
sysinfo
(
&
si
);
julong
avail_mem
;
if
(
OSContainer
::
is_containerized
())
{
jlong
mem_limit
,
mem_usage
;
if
((
mem_limit
=
OSContainer
::
memory_limit_in_bytes
())
<
1
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"container memory limit %s: "
JLONG_FORMAT
", using host value"
,
mem_limit
==
OSCONTAINER_ERROR
?
"failed"
:
"unlimited"
,
mem_limit
);
}
}
return
(
julong
)
si
.
freeram
*
si
.
mem_unit
;
if
(
mem_limit
>
0
&&
(
mem_usage
=
OSContainer
::
memory_usage_in_bytes
())
<
1
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"container memory usage failed: "
JLONG_FORMAT
", using host value"
,
mem_usage
);
}
}
if
(
mem_limit
>
0
&&
mem_usage
>
0
)
{
avail_mem
=
mem_limit
>
mem_usage
?
(
julong
)
mem_limit
-
(
julong
)
mem_usage
:
0
;
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"available container memory: "
JULONG_FORMAT
,
avail_mem
);
}
return
avail_mem
;
}
}
sysinfo
(
&
si
);
avail_mem
=
(
julong
)
si
.
freeram
*
si
.
mem_unit
;
if
(
Verbose
)
{
tty
->
print_cr
(
"available memory: "
JULONG_FORMAT
,
avail_mem
);
}
return
avail_mem
;
}
julong
os
::
physical_memory
()
{
return
Linux
::
physical_memory
();
jlong
phys_mem
=
0
;
if
(
OSContainer
::
is_containerized
())
{
jlong
mem_limit
;
if
((
mem_limit
=
OSContainer
::
memory_limit_in_bytes
())
>
0
)
{
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"total container memory: "
JLONG_FORMAT
,
mem_limit
);
}
return
mem_limit
;
}
if
(
PrintContainerInfo
)
{
tty
->
print_cr
(
"container memory limit %s: "
JLONG_FORMAT
", using host value"
,
mem_limit
==
OSCONTAINER_ERROR
?
"failed"
:
"unlimited"
,
mem_limit
);
}
}
phys_mem
=
Linux
::
physical_memory
();
if
(
Verbose
)
{
tty
->
print_cr
(
"total system memory: "
JLONG_FORMAT
,
phys_mem
);
}
return
phys_mem
;
}
////////////////////////////////////////////////////////////////////////////////
...
...
@@ -2114,6 +2164,8 @@ void os::print_os_info(outputStream* st) {
os
::
Posix
::
print_load_average
(
st
);
os
::
Linux
::
print_full_memory_info
(
st
);
os
::
Linux
::
print_container_info
(
st
);
}
// Try to identify popular distros.
...
...
@@ -2179,6 +2231,57 @@ void os::Linux::print_full_memory_info(outputStream* st) {
st
->
cr
();
}
void
os
::
Linux
::
print_container_info
(
outputStream
*
st
)
{
if
(
!
OSContainer
::
is_containerized
())
{
return
;
}
st
->
print
(
"container (cgroup) information:
\n
"
);
const
char
*
p_ct
=
OSContainer
::
container_type
();
st
->
print
(
"container_type: %s
\n
"
,
p_ct
!=
NULL
?
p_ct
:
"failed"
);
char
*
p
=
OSContainer
::
cpu_cpuset_cpus
();
st
->
print
(
"cpu_cpuset_cpus: %s
\n
"
,
p
!=
NULL
?
p
:
"failed"
);
free
(
p
);
p
=
OSContainer
::
cpu_cpuset_memory_nodes
();
st
->
print
(
"cpu_memory_nodes: %s
\n
"
,
p
!=
NULL
?
p
:
"failed"
);
free
(
p
);
int
i
=
OSContainer
::
active_processor_count
();
if
(
i
>
0
)
{
st
->
print
(
"active_processor_count: %d
\n
"
,
i
);
}
else
{
st
->
print
(
"active_processor_count: failed
\n
"
);
}
i
=
OSContainer
::
cpu_quota
();
st
->
print
(
"cpu_quota: %d
\n
"
,
i
);
i
=
OSContainer
::
cpu_period
();
st
->
print
(
"cpu_period: %d
\n
"
,
i
);
i
=
OSContainer
::
cpu_shares
();
st
->
print
(
"cpu_shares: %d
\n
"
,
i
);
jlong
j
=
OSContainer
::
memory_limit_in_bytes
();
st
->
print
(
"memory_limit_in_bytes: "
JLONG_FORMAT
"
\n
"
,
j
);
j
=
OSContainer
::
memory_and_swap_limit_in_bytes
();
st
->
print
(
"memory_and_swap_limit_in_bytes: "
JLONG_FORMAT
"
\n
"
,
j
);
j
=
OSContainer
::
memory_soft_limit_in_bytes
();
st
->
print
(
"memory_soft_limit_in_bytes: "
JLONG_FORMAT
"
\n
"
,
j
);
j
=
OSContainer
::
OSContainer
::
memory_usage_in_bytes
();
st
->
print
(
"memory_usage_in_bytes: "
JLONG_FORMAT
"
\n
"
,
j
);
j
=
OSContainer
::
OSContainer
::
memory_max_usage_in_bytes
();
st
->
print
(
"memory_max_usage_in_bytes: "
JLONG_FORMAT
"
\n
"
,
j
);
st
->
cr
();
}
void
os
::
print_memory_info
(
outputStream
*
st
)
{
st
->
print
(
"Memory:"
);
...
...
@@ -4951,6 +5054,10 @@ extern "C" {
}
}
void
os
::
pd_init_container_support
()
{
OSContainer
::
init
();
}
// this is called _after_ the global arguments have been parsed
jint
os
::
init_2
(
void
)
{
...
...
@@ -5131,7 +5238,7 @@ static int os_cpu_count(const cpu_set_t* cpus) {
// sched_getaffinity gives an accurate answer as it accounts for cpusets.
// If anything goes wrong we fallback to returning the number of online
// processors - which can be greater than the number available to the process.
int
os
::
active_processor_count
()
{
int
os
::
Linux
::
active_processor_count
()
{
cpu_set_t
cpus
;
// can represent at most 1024 (CPU_SETSIZE) processors
int
cpus_size
=
sizeof
(
cpu_set_t
);
int
cpu_count
=
0
;
...
...
@@ -5149,10 +5256,48 @@ int os::active_processor_count() {
"which may exceed available processors"
,
strerror
(
errno
),
cpu_count
);
}
assert
(
cpu_count
>
0
&&
cpu_count
<=
processor_count
(),
"sanity check"
);
assert
(
cpu_count
>
0
&&
cpu_count
<=
os
::
processor_count
(),
"sanity check"
);
return
cpu_count
;
}
// Determine the active processor count from one of
// three different sources:
//
// 1. User option -XX:ActiveProcessorCount
// 2. kernel os calls (sched_getaffinity or sysconf(_SC_NPROCESSORS_ONLN)
// 3. extracted from cgroup cpu subsystem (shares and quotas)
//
// Option 1, if specified, will always override.
// If the cgroup subsystem is active and configured, we
// will return the min of the cgroup and option 2 results.
// This is required since tools, such as numactl, that
// alter cpu affinity do not update cgroup subsystem
// cpuset configuration files.
int
os
::
active_processor_count
()
{
// User has overridden the number of active processors
if
(
ActiveProcessorCount
>
0
)
{
if
(
PrintActiveCpus
)
{
tty
->
print_cr
(
"active_processor_count: "
"active processor count set by user : %d"
,
ActiveProcessorCount
);
}
return
ActiveProcessorCount
;
}
int
active_cpus
;
if
(
OSContainer
::
is_containerized
())
{
active_cpus
=
OSContainer
::
active_processor_count
();
if
(
PrintActiveCpus
)
{
tty
->
print_cr
(
"active_processor_count: determined by OSContainer: %d"
,
active_cpus
);
}
}
else
{
active_cpus
=
os
::
Linux
::
active_processor_count
();
}
return
active_cpus
;
}
void
os
::
set_native_thread_name
(
const
char
*
name
)
{
// Not yet implemented.
return
;
...
...
src/os/linux/vm/os_linux.hpp
浏览文件 @
1de115b4
...
...
@@ -35,6 +35,7 @@ static bool zero_page_read_protected() { return true; }
class
Linux
{
friend
class
os
;
friend
class
OSContainer
;
friend
class
TestReserveMemorySpecial
;
// For signal-chaining
...
...
@@ -79,6 +80,9 @@ class Linux {
static
julong
available_memory
();
static
julong
physical_memory
()
{
return
_physical_memory
;
}
static
void
set_physical_memory
(
julong
phys_mem
)
{
_physical_memory
=
phys_mem
;
}
static
int
active_processor_count
();
static
void
initialize_system_info
();
static
int
commit_memory_impl
(
char
*
addr
,
size_t
bytes
,
bool
exec
);
...
...
@@ -116,6 +120,7 @@ class Linux {
static
bool
release_memory_special_huge_tlbfs
(
char
*
base
,
size_t
bytes
);
static
void
print_full_memory_info
(
outputStream
*
st
);
static
void
print_container_info
(
outputStream
*
st
);
static
void
print_distro_info
(
outputStream
*
st
);
static
void
print_libversion_info
(
outputStream
*
st
);
...
...
src/os/solaris/vm/os_solaris.cpp
浏览文件 @
1de115b4
...
...
@@ -357,6 +357,16 @@ void os::Solaris::initialize_system_info() {
}
int
os
::
active_processor_count
()
{
// User has overridden the number of active processors
if
(
ActiveProcessorCount
>
0
)
{
if
(
Verbose
)
{
tty
->
print_cr
(
"active_processor_count: "
"active processor count set by user : %d"
,
ActiveProcessorCount
);
}
return
ActiveProcessorCount
;
}
int
online_cpus
=
sysconf
(
_SC_NPROCESSORS_ONLN
);
pid_t
pid
=
getpid
();
psetid_t
pset
=
PS_NONE
;
...
...
src/os/windows/vm/os_windows.cpp
浏览文件 @
1de115b4
...
...
@@ -716,6 +716,16 @@ typedef UINT_PTR DWORD_PTR;
#endif
int
os
::
active_processor_count
()
{
// User has overridden the number of active processors
if
(
ActiveProcessorCount
>
0
)
{
if
(
PrintActiveCpus
)
{
tty
->
print_cr
(
"active_processor_count: "
"active processor count set by user : %d"
,
ActiveProcessorCount
);
}
return
ActiveProcessorCount
;
}
DWORD_PTR
lpProcessAffinityMask
=
0
;
DWORD_PTR
lpSystemAffinityMask
=
0
;
int
proc_count
=
processor_count
();
...
...
src/share/vm/runtime/arguments.cpp
浏览文件 @
1de115b4
/*
* Copyright (c) 1997, 201
7
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
8
, 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
...
...
@@ -1801,20 +1801,34 @@ void Arguments::set_heap_size() {
}
}
// Convert Fraction to Precentage values
if
(
FLAG_IS_DEFAULT
(
MaxRAMPercentage
)
&&
!
FLAG_IS_DEFAULT
(
MaxRAMFraction
))
MaxRAMPercentage
=
100.0
/
MaxRAMFraction
;
if
(
FLAG_IS_DEFAULT
(
MinRAMPercentage
)
&&
!
FLAG_IS_DEFAULT
(
MinRAMFraction
))
MinRAMPercentage
=
100.0
/
MinRAMFraction
;
if
(
FLAG_IS_DEFAULT
(
InitialRAMPercentage
)
&&
!
FLAG_IS_DEFAULT
(
InitialRAMFraction
))
InitialRAMPercentage
=
100.0
/
InitialRAMFraction
;
// If the maximum heap size has not been set with -Xmx,
// then set it as fraction of the size of physical memory,
// respecting the maximum and minimum sizes of the heap.
if
(
FLAG_IS_DEFAULT
(
MaxHeapSize
))
{
julong
reasonable_max
=
phys_mem
/
MaxRAMFraction
;
if
(
phys_mem
<=
MaxHeapSize
*
MinRAMFraction
)
{
julong
reasonable_max
=
(
julong
)((
phys_mem
*
MaxRAMPercentage
)
/
100
)
;
const
julong
reasonable_min
=
(
julong
)((
phys_mem
*
MinRAMPercentage
)
/
100
);
if
(
reasonable_min
<
MaxHeapSize
)
{
// Small physical memory, so use a minimum fraction of it for the heap
reasonable_max
=
phys_mem
/
MinRAMFractio
n
;
reasonable_max
=
reasonable_mi
n
;
}
else
{
// Not-small physical memory, so require a heap at least
// as large as MaxHeapSize
reasonable_max
=
MAX2
(
reasonable_max
,
(
julong
)
MaxHeapSize
);
}
if
(
!
FLAG_IS_DEFAULT
(
ErgoHeapSizeLimit
)
&&
ErgoHeapSizeLimit
!=
0
)
{
// Limit the heap size to ErgoHeapSizeLimit
reasonable_max
=
MIN2
(
reasonable_max
,
(
julong
)
ErgoHeapSizeLimit
);
...
...
@@ -1856,7 +1870,7 @@ void Arguments::set_heap_size() {
reasonable_minimum
=
limit_by_allocatable_memory
(
reasonable_minimum
);
if
(
InitialHeapSize
==
0
)
{
julong
reasonable_initial
=
phys_mem
/
InitialRAMFraction
;
julong
reasonable_initial
=
(
julong
)((
phys_mem
*
InitialRAMPercentage
)
/
100
)
;
reasonable_initial
=
MAX3
(
reasonable_initial
,
reasonable_minimum
,
(
julong
)
min_heap_size
());
reasonable_initial
=
MIN2
(
reasonable_initial
,
(
julong
)
MaxHeapSize
);
...
...
@@ -1881,6 +1895,94 @@ void Arguments::set_heap_size() {
}
}
// This option inspects the machine and attempts to set various
// parameters to be optimal for long-running, memory allocation
// intensive jobs. It is intended for machines with large
// amounts of cpu and memory.
jint
Arguments
::
set_aggressive_heap_flags
()
{
// initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
// VM, but we may not be able to represent the total physical memory
// available (like having 8gb of memory on a box but using a 32bit VM).
// Thus, we need to make sure we're using a julong for intermediate
// calculations.
julong
initHeapSize
;
julong
total_memory
=
os
::
physical_memory
();
if
(
total_memory
<
(
julong
)
256
*
M
)
{
jio_fprintf
(
defaultStream
::
error_stream
(),
"You need at least 256mb of memory to use -XX:+AggressiveHeap
\n
"
);
vm_exit
(
1
);
}
// The heap size is half of available memory, or (at most)
// all of possible memory less 160mb (leaving room for the OS
// when using ISM). This is the maximum; because adaptive sizing
// is turned on below, the actual space used may be smaller.
initHeapSize
=
MIN2
(
total_memory
/
(
julong
)
2
,
total_memory
-
(
julong
)
160
*
M
);
initHeapSize
=
limit_by_allocatable_memory
(
initHeapSize
);
if
(
FLAG_IS_DEFAULT
(
MaxHeapSize
))
{
FLAG_SET_CMDLINE
(
uintx
,
MaxHeapSize
,
initHeapSize
);
FLAG_SET_CMDLINE
(
uintx
,
InitialHeapSize
,
initHeapSize
);
// Currently the minimum size and the initial heap sizes are the same.
set_min_heap_size
(
initHeapSize
);
}
if
(
FLAG_IS_DEFAULT
(
NewSize
))
{
// Make the young generation 3/8ths of the total heap.
FLAG_SET_CMDLINE
(
uintx
,
NewSize
,
((
julong
)
MaxHeapSize
/
(
julong
)
8
)
*
(
julong
)
3
);
FLAG_SET_CMDLINE
(
uintx
,
MaxNewSize
,
NewSize
);
}
#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
FLAG_SET_DEFAULT
(
UseLargePages
,
true
);
#endif
// Increase some data structure sizes for efficiency
FLAG_SET_CMDLINE
(
uintx
,
BaseFootPrintEstimate
,
MaxHeapSize
);
FLAG_SET_CMDLINE
(
bool
,
ResizeTLAB
,
false
);
FLAG_SET_CMDLINE
(
uintx
,
TLABSize
,
256
*
K
);
// See the OldPLABSize comment below, but replace 'after promotion'
// with 'after copying'. YoungPLABSize is the size of the survivor
// space per-gc-thread buffers. The default is 4kw.
FLAG_SET_CMDLINE
(
uintx
,
YoungPLABSize
,
256
*
K
);
// Note: this is in words
// OldPLABSize is the size of the buffers in the old gen that
// UseParallelGC uses to promote live data that doesn't fit in the
// survivor spaces. At any given time, there's one for each gc thread.
// The default size is 1kw. These buffers are rarely used, since the
// survivor spaces are usually big enough. For specjbb, however, there
// are occasions when there's lots of live data in the young gen
// and we end up promoting some of it. We don't have a definite
// explanation for why bumping OldPLABSize helps, but the theory
// is that a bigger PLAB results in retaining something like the
// original allocation order after promotion, which improves mutator
// locality. A minor effect may be that larger PLABs reduce the
// number of PLAB allocation events during gc. The value of 8kw
// was arrived at by experimenting with specjbb.
FLAG_SET_CMDLINE
(
uintx
,
OldPLABSize
,
8
*
K
);
// Note: this is in words
// Enable parallel GC and adaptive generation sizing
FLAG_SET_CMDLINE
(
bool
,
UseParallelGC
,
true
);
// Encourage steady state memory management
FLAG_SET_CMDLINE
(
uintx
,
ThresholdTolerance
,
100
);
// This appears to improve mutator locality
FLAG_SET_CMDLINE
(
bool
,
ScavengeBeforeFullGC
,
false
);
// Get around early Solaris scheduling bug
// (affinity vs other jobs on system)
// but disallow DR and offlining (5008695).
FLAG_SET_CMDLINE
(
bool
,
BindGCTaskThreadsToCPUs
,
true
);
return
JNI_OK
;
}
// This must be called after ergonomics because we want bytecode rewriting
// if the server compiler is used, or if UseSharedSpaces is disabled.
void
Arguments
::
set_bytecode_flags
()
{
...
...
@@ -2644,6 +2746,14 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) {
return
result
;
}
// We need to ensure processor and memory resources have been properly
// configured - which may rely on arguments we just processed - before
// doing the final argument processing. Any argument processing that
// needs to know about processor and memory resources must occur after
// this point.
os
::
init_container_support
();
// Do final processing now that all arguments have been parsed
result
=
finalize_vm_init_args
(
&
scp
,
scp_assembly_required
);
if
(
result
!=
JNI_OK
)
{
...
...
@@ -3117,94 +3227,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
_exit_hook
=
CAST_TO_FN_PTR
(
exit_hook_t
,
option
->
extraInfo
);
}
else
if
(
match_option
(
option
,
"abort"
,
&
tail
))
{
_abort_hook
=
CAST_TO_FN_PTR
(
abort_hook_t
,
option
->
extraInfo
);
// -XX:+AggressiveHeap
}
else
if
(
match_option
(
option
,
"-XX:+AggressiveHeap"
,
&
tail
))
{
// This option inspects the machine and attempts to set various
// parameters to be optimal for long-running, memory allocation
// intensive jobs. It is intended for machines with large
// amounts of cpu and memory.
// initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
// VM, but we may not be able to represent the total physical memory
// available (like having 8gb of memory on a box but using a 32bit VM).
// Thus, we need to make sure we're using a julong for intermediate
// calculations.
julong
initHeapSize
;
julong
total_memory
=
os
::
physical_memory
();
if
(
total_memory
<
(
julong
)
256
*
M
)
{
jio_fprintf
(
defaultStream
::
error_stream
(),
"You need at least 256mb of memory to use -XX:+AggressiveHeap
\n
"
);
vm_exit
(
1
);
}
// The heap size is half of available memory, or (at most)
// all of possible memory less 160mb (leaving room for the OS
// when using ISM). This is the maximum; because adaptive sizing
// is turned on below, the actual space used may be smaller.
initHeapSize
=
MIN2
(
total_memory
/
(
julong
)
2
,
total_memory
-
(
julong
)
160
*
M
);
initHeapSize
=
limit_by_allocatable_memory
(
initHeapSize
);
if
(
FLAG_IS_DEFAULT
(
MaxHeapSize
))
{
FLAG_SET_CMDLINE
(
uintx
,
MaxHeapSize
,
initHeapSize
);
FLAG_SET_CMDLINE
(
uintx
,
InitialHeapSize
,
initHeapSize
);
// Currently the minimum size and the initial heap sizes are the same.
set_min_heap_size
(
initHeapSize
);
}
if
(
FLAG_IS_DEFAULT
(
NewSize
))
{
// Make the young generation 3/8ths of the total heap.
FLAG_SET_CMDLINE
(
uintx
,
NewSize
,
((
julong
)
MaxHeapSize
/
(
julong
)
8
)
*
(
julong
)
3
);
FLAG_SET_CMDLINE
(
uintx
,
MaxNewSize
,
NewSize
);
}
#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
FLAG_SET_DEFAULT
(
UseLargePages
,
true
);
#endif
// Increase some data structure sizes for efficiency
FLAG_SET_CMDLINE
(
uintx
,
BaseFootPrintEstimate
,
MaxHeapSize
);
FLAG_SET_CMDLINE
(
bool
,
ResizeTLAB
,
false
);
FLAG_SET_CMDLINE
(
uintx
,
TLABSize
,
256
*
K
);
// See the OldPLABSize comment below, but replace 'after promotion'
// with 'after copying'. YoungPLABSize is the size of the survivor
// space per-gc-thread buffers. The default is 4kw.
FLAG_SET_CMDLINE
(
uintx
,
YoungPLABSize
,
256
*
K
);
// Note: this is in words
// OldPLABSize is the size of the buffers in the old gen that
// UseParallelGC uses to promote live data that doesn't fit in the
// survivor spaces. At any given time, there's one for each gc thread.
// The default size is 1kw. These buffers are rarely used, since the
// survivor spaces are usually big enough. For specjbb, however, there
// are occasions when there's lots of live data in the young gen
// and we end up promoting some of it. We don't have a definite
// explanation for why bumping OldPLABSize helps, but the theory
// is that a bigger PLAB results in retaining something like the
// original allocation order after promotion, which improves mutator
// locality. A minor effect may be that larger PLABs reduce the
// number of PLAB allocation events during gc. The value of 8kw
// was arrived at by experimenting with specjbb.
FLAG_SET_CMDLINE
(
uintx
,
OldPLABSize
,
8
*
K
);
// Note: this is in words
// Enable parallel GC and adaptive generation sizing
FLAG_SET_CMDLINE
(
bool
,
UseParallelGC
,
true
);
// Encourage steady state memory management
FLAG_SET_CMDLINE
(
uintx
,
ThresholdTolerance
,
100
);
// This appears to improve mutator locality
FLAG_SET_CMDLINE
(
bool
,
ScavengeBeforeFullGC
,
false
);
// Get around early Solaris scheduling bug
// (affinity vs other jobs on system)
// but disallow DR and offlining (5008695).
FLAG_SET_CMDLINE
(
bool
,
BindGCTaskThreadsToCPUs
,
true
);
}
else
if
(
match_option
(
option
,
"-XX:+NeverTenure"
,
&
tail
))
{
// The last option must always win.
FLAG_SET_CMDLINE
(
bool
,
AlwaysTenure
,
false
);
...
...
@@ -3605,6 +3627,15 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req
return
JNI_ERR
;
}
// This must be done after all arguments have been processed
// and the container support has been initialized since AggressiveHeap
// relies on the amount of total memory available.
if
(
AggressiveHeap
)
{
jint
result
=
set_aggressive_heap_flags
();
if
(
result
!=
JNI_OK
)
{
return
result
;
}
}
// This must be done after all arguments have been processed.
// java_compiler() true means set to "NONE" or empty.
if
(
java_compiler
()
&&
!
xdebug_mode
())
{
...
...
src/share/vm/runtime/arguments.hpp
浏览文件 @
1de115b4
/*
* Copyright (c) 1997, 201
4
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 201
8
, 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
...
...
@@ -365,6 +365,8 @@ class Arguments : AllStatic {
// Aggressive optimization flags.
static
void
set_aggressive_opts_flags
();
static
jint
set_aggressive_heap_flags
();
// Argument parsing
static
void
do_pd_flag_adjustments
();
static
bool
parse_argument
(
const
char
*
arg
,
Flag
::
Flags
origin
);
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
1de115b4
...
...
@@ -2064,13 +2064,23 @@ class CommandLineFlags {
product_pd(uint64_t, MaxRAM, \
"Real memory size (in bytes) used to set maximum heap size") \
\
product(bool, AggressiveHeap, false, \
"Optimize heap options for long-running memory intensive apps") \
\
product(uintx, ErgoHeapSizeLimit, 0, \
"Maximum ergonomically set heap size (in bytes); zero means use " \
"MaxRAM
/ MaxRAMFraction")
\
"MaxRAM
* MaxRAMPercentage / 100")
\
\
experimental(bool, UseCGroupMemoryLimitForHeap, false, \
"Use CGroup memory limit as physical memory limit for heap " \
"sizing") \
"sizing" \
"Deprecated, replaced by container support") \
\
diagnostic(bool, PrintContainerInfo, false, \
"Print container related information") \
\
diagnostic(bool, PrintActiveCpus, false, \
"Print the number of CPUs detected in os::active_processor_count") \
\
product(uintx, MaxRAMFraction, 4, \
"Maximum fraction (1/n) of real memory used for maximum heap " \
...
...
@@ -2087,6 +2097,19 @@ class CommandLineFlags {
product(uintx, InitialRAMFraction, 64, \
"Fraction (1/n) of real memory used for initial heap size") \
\
product(double, MaxRAMPercentage, 25.0, \
"Maximum percentage of real memory used for maximum heap size") \
\
product(double, MinRAMPercentage, 50.0, \
"Minimum percentage of real memory used for maximum heap" \
"size on systems with small physical memory size") \
\
product(double, InitialRAMPercentage, 1.5625, \
"Percentage of real memory used for initial heap size") \
\
product(intx, ActiveProcessorCount, -1, \
"Specify the CPU count the VM should use and report as active") \
\
develop(uintx, MaxVirtMemFraction, 2, \
"Maximum fraction (1/n) of virtual memory used for ergonomically "\
"determining maximum heap size") \
...
...
src/share/vm/runtime/os.hpp
浏览文件 @
1de115b4
...
...
@@ -152,8 +152,16 @@ class os: AllStatic {
static
size_t
page_size_for_region
(
size_t
region_size
,
size_t
min_pages
,
bool
must_be_aligned
);
static
void
initialize_initial_active_processor_count
();
LINUX_ONLY
(
static
void
pd_init_container_support
();)
public:
static
void
init
(
void
);
// Called before command line parsing
static
void
init_container_support
()
{
// Called during command line parsing.
LINUX_ONLY
(
pd_init_container_support
();)
}
static
void
init_before_ergo
(
void
);
// Called after command line parsing
// before VM ergonomics processing.
static
jint
init_2
(
void
);
// Called after command line parsing
...
...
src/share/vm/runtime/thread.cpp
浏览文件 @
1de115b4
...
...
@@ -3335,6 +3335,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
Arguments
::
init_version_specific_system_properties
();
// Parse arguments
// Note: this internally calls os::init_container_support()
jint
parse_result
=
Arguments
::
parse
(
args
);
if
(
parse_result
!=
JNI_OK
)
return
parse_result
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录