G1从入门到放弃(二)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了G1从入门到放弃(二)相关的知识,希望对你有一定的参考价值。
参考技术A上一篇文章主要讲了G1的理论知识,本篇文章会讲解在实际生产中如何读懂G1日志,以及介绍G1的参数配置。
通过使用 -XX:+PrintGCDetails 参数查看的Young GC日志如下:
① 四个关键信息
② 所有并行任务
③ 串行任务
④其他事项
其他事项共耗时3.7ms,其他事项包括选择CSet,处理已用对象,引用入ReferenceQueues,释放CSet中的region。
⑤各代变化
⑥ 这次回收耗时
①标明标记阶段开始
③并发标记
④ STW阶段
⑤ 这也是STW阶段
- GC cleanup : 这个阶段没有存活对象的Old Region和Humongous Region将被释放和清空。为了准备下次GC,在CSets中的Old Regions会根据他们的回收收益的大小排序。为了准备下一次标记,previous bitmaps 和 next bitmaps会被交换。同时并行线程会标记那些inital mark阶段生成的对象,以及至少存在一个存活对象的region的bitmap。
⑥这也是一个并发阶段
当并发标记完成后,在Young GC日志后面紧随着Mixed GC,下面是Mixed GC日志。可以看到Mixed GC日志和前面介绍的Young GC很相似,只有两个不同点:
1、第一行会表示这是一个Mixed GC
2、收集的集合里包含了老年代(Old Region),由并发标记阶段确定的。
Full GC的日志结果如下。
需要注意的是如果是几天一次Full GC,则是正常现象,但是每小时频繁GC就需要调优了。
建议大家开启 -XX:+PrintAdaptiveSizePolicy 和 -XX:+PrintTenuringDistribution 两个标签,可以帮助大家更好的分析日志。
Young GC开启 -XX:+PrintAdaptiveSizePolicy 之后的日志如下:
① 告诉我们有多少在dirty card队列里的cards等待被处理。并且展示了预计处理时间(包括了更新RSet和扫描RSet的时间);
② 有多少Region将被加入到这次GC中
③ 选择出CSets并且估算这次收集时间
④ 该行并不一定在Young GC日志中出现,如果花费在GC上的时间比应用线程大到一个阈值的时候,G1可以动态扩大堆大小。 如果你设置了最大堆和最小堆的大小相等,该行不会出现
⑤ 当并发标记开始时出现。
Young GC后面是并发回收日志。
Young GC日志中还可能存在关于Mixed GC的日志:
①告诉我们Mixed GC开始,原因是可回收垃圾百分比(22.62%)大于了我们的阈值(5%)。
下面是Mixed GC开启 -XX:+PrintAdaptiveSizePolicy 之后执行日志
① 该阶段包括CSet和一部分Young Region的选择
②描述Mixed GC时,Old Region被加入到CSet中。默认情况下,G1只把10%的Old Region加入到CSet中,通过配置 -XX:G1OldCSetRegionThresholdPercent=X 可以更改
③提供最终的CSet和停顿预测
④描述Mixed GC状态细节。在这个案例中,我们仍然有535个Old Region可以被回收,大约305363768字节,占整个堆大小的14.22%。由于仍然大于阈值,下个阶段回收仍然是Mixed GC。
下面是Full GC开启 -XX:+PrintAdaptiveSizePolicy 之后执行日志
① 没有空的Region用来分配对象,请求扩容堆
② 扩容需要多少空间。到目前为止还没有真正执行扩容。
③ 不会尝试扩容。因为没有可用的Region,所有要执行Full GC。
④ 在最小堆小于最大堆时出现的日志。G1 在一次Full GC后,尝试缩小堆到70%。这个百分比可以通过 -XX:InitiatingHeapOccupancyPercent (IHOP)调节,这个参数设置使用整个对的x%时,系统开始进行并行GC。注意是整个堆的百分比。
⑤ 堆正在被缩小,已经缩小了多少容量。
-XX:+PrintTenuringDistribution : 可以查看每次回收期间,Survivor区的分布信息。可以帮助我们查看对象年龄的变化。
上图主要从三个层面展示Survivor区:
-desired survivor size: 期望的Survivor大小。该值等于Survivor大小乘以TargetSurvivorRatio (默认50%)。
webpack 从入门到放弃
var moduleA = function(){
var a, b;
return {
message: function(c){
alert(a+b+c)
}
}
}()
(function(window){
// do something
window.jQuery = window.$ = jQuery;
})(window)
var math = require(‘math‘);
- math.add(2, 3);
require([‘math‘], function(math){
math.add(2,3)
})
import math from ‘math‘;
math.add(2, 3);
前端的模块加载:
require(‘./style.css‘);
require(‘./style.less‘);
require(‘./style.jade‘);
require(‘./image.png‘);
- 可以链式调用,我处理完了交给你接着处理,但是最后一个loader必须返回javascript
- loader 可以同步或者异步执行
- loader 可以运行在 nodejs中,所以可能做任何事情
- loader 通过参数来传递配置
- 插件让loader 有更多的特性
var webpack = require(‘webpack‘);
module.exports = {
entry: ‘./entry.js‘,
output: {
path: __dirname,
filename: ‘bundle.js‘
},
module:{
loaders: [
{test: /\\.css$/, loader: ‘style-loader!css-loader‘}
]
}
}
var webpack = require(‘webpack‘);
module.exports = {
entry: ‘./entry.js‘,
output: {
filename: ‘bundle.js‘
},
module: {
loaders: [
{ test:/\\.css$/, loader: ‘style-loader!css-loader‘}
]
},
plugin: [
new webpack.BannerPlugin(‘dujuncheng created‘)
]
}
1. 安装
npm init
cnpm install webpack --save
"dependencies": {
"webpack": "^2.5.1"
}
2. webpack 会自动将文件进行打包
// index.html
<div id=‘app‘></div>
<script src = ‘bundle.js‘>
//entry.js
document.getElementById(‘app‘).textContent = ‘hello‘
webpack entry.js bundle.js
3. webpack 会自动分析 依赖,
module.exports = ‘dujuncheng‘
var name = require(‘./name‘);
document.getElementById(‘app‘).textContent=‘hello‘+name
webpack entry.js bundle.js
4. loader
cnpm install css-loader style-loader --save
"dependencies": {
"css-loader": "^0.28.1",
"style-loader": "^0.17.0",
"webpack": "^2.5.1"
}
module.exports = {
entry: ‘./entry.js‘,
output: {
path: __dirname,
filename: ‘bundle.js‘
},
module: {
loaders:[
{ test:/\\.css$/, loader: ‘style-loader!css-loader‘ }
]
}
}
body {
background-color: red
}
//entry.js
require(‘./style.css‘);
document.getElementById(‘app‘).textContent = ‘dujuncheng‘ ;
// 因为我们配置了webpack.config.js 配置文件,所以我们只要 webpack 就可以打包了
webpack
5. source map
webpack --devtool source-map
module.exports = {
entry: ‘./entry.js‘,
output: {
path: __dirname,
filename: ‘bundle.js‘
},
devtool: ‘source-map‘,
module: {
loaders: [
{
test: /\\.css$/,
loader: ‘style-loader!css-loader‘
}
]
}
}
cnpm install babel-loader babel-core babel-preset-es2015 --save-dev
npm install --save-dev webpack-bundle-analyzer
//webpack.config.js
var BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer‘).BundleAnalyzerPlugin;
// ...
plugins: [new BundleAnalyzerPlugin()]
// ...
new webpack.optimize.CommonsChunkPlugin({
name: ‘vendor‘,
minChunks: ({ resource }) => (
resource && resource.indexOf(‘node_modules‘) >= 0 && resource.match(/\\.js$/))
}),
// import test1 from ‘@/components/test1‘
// import test2 from ‘@/components/test2‘
// import test3 from ‘@/components/test3‘
const test1 = () => import(
/* webpackChunkName: "Emoji" */
‘@/components/test1‘)
const test2 = () => import(
/* webpackChunkName: "Emoji" */
‘@/components/test2‘)
const test3 = () => import(
/* webpackChunkName: "Emoji" */
‘@/components/test3‘)
filename: ‘[name].js‘,
chunkFilename: ‘[name].chunk.js‘,
{
"plugins": ["syntax-dynamic-import"]
}
以上是关于G1从入门到放弃(二)的主要内容,如果未能解决你的问题,请参考以下文章