当前位置: 首页 > news >正文

平台宣传推广方案自动优化句子的软件

平台宣传推广方案,自动优化句子的软件,wordpress 图片自述,wordpress左侧导航菜单1.JVM内部的优化逻辑 1.1JVM的执行引擎 javac编译器将Person.java源码文件编译成class文件[我们把这里的编译称为前期编译]#xff0c;交给JVM运行#xff0c;因为JVM只能认识class字节码文件。同时在不同的操作系统上安装对应版本的JDK#xff0c;里面包含了各自屏蔽操作…1.JVM内部的优化逻辑 1.1JVM的执行引擎 javac编译器将Person.java源码文件编译成class文件[我们把这里的编译称为前期编译]交给JVM运行因为JVM只能认识class字节码文件。同时在不同的操作系统上安装对应版本的JDK里面包含了各自屏蔽操作系统底层细节的JVM这样同一份class文件就能运行在不同的操作系统平台之上得益于JVM。这也是Write OnceRun Anywhere的原因所在。 最终JVM需要把字节码指令转换为机器码可以理解为是0101这样的机器语言这样才能运行在不同的机器上那么由字节码转变为机器码是谁来做的呢说白了就是谁来执行这些字节码指令的呢这就是执行引擎 1.1.1解释执行 Interpreter解释器逐条把字节码翻译成机器码并执行跨平台的保证。 刚开始执行引擎只采用了解释执行的但是后来发现某些方法或者代码块被调用执行的特别频繁时就会把这些代码认定为“热点代码”。 1.1.2即时编译器 Just-In-Time compilation(JIT)即时编译器先将字节码编译成对应平台的可执行文件运行速度快。即时编译器会把这些热点代码编译成与本地平台关联的机器码并且进行各层次的优化保存到内存中。 1.1.2.1即时编译器类型 1HotSpot虚拟机里面内置了两个JITC1和C2 C1也称为Client Compiler适用于执行时间短或者对启动性能有要求的程序 C2也称为Server Compiler适用于执行时间长或者对峰值性能有要求的程序 2Java7开始HotSpot会使用分层编译的方式 分层编译也就是会结合C1的启动性能优势和C2的峰值性能优势热点方法会先被C1编译然后热点方法中的热点会被C2再次编译  -XX:TieredCompilation开启参数 1.1.3JVM采用哪种方式 JVM采取的是混合模式也就是解释编译的方式对于大部分不常用的代码不需要浪费时间将其编译成机器码只需要用到的时候再以解释的方式运行对于小部分的热点代码可以采取编译的方式追求更高的运行效率。 1.2JVM的分层编译5大级别 0.解释执行 1.简单的C1编译仅仅使用我们的C1做一些简单的优化不会开启Profiling 2.受限的C1编译代码只会执行我们的方法调用次数以及循环的回边次数多次执行的循环体Profiling的C1编译 3.完全C1编译代码我们Profiling里面所有的代码。也会被C1执行 4.C2编译代码这个才是优化的级别。 级别越高我们的应用启动越慢优化下来开销会越高同样的我们的峰值性能也会越高 通常C2 代码的执行效率要比 C1 代码的高出 30% 以上 1和4为终止状态1,4经过一次编译后依然在1,4中那1,4就不会编译了 Java 虚拟机内置了 profiling。 profiling 是指在程序执行过程中收集能够反映程序执行状态的数据。这里所收集的数据我们称之为程序的 profile。 方法2如果方法的字节码数目比较少如 getter/setter而且 3 层的 profiling 没有可收集的数据。那么Java 虚拟机断定该方法对于 C1 代码和 C2 代码的执行效率相同。在这种情况下Java 虚拟机会在 3 层编译之后直接选择用 1 层的 C1 编译。由于这是一个终止状态因此 Java 虚拟机不会继续用 4 层的 C2 编译。 方法3在 C1 忙碌的情况下Java 虚拟机在解释执行过程中对程序进行 profiling而后直接由 4 层的 C2 编译。 方法4在 C2 忙碌的情况下方法会被 2 层的 C1 编译然后再被 3 层的 C1 编译以减少方法在 3 层的执行时间。 Java 8 默认开启了分层编译。-XX:TieredCompilation开启参数 不管是开启还是关闭分层编译原本用来选择即时编译器的参数 -client 和 -server都是无效的。当关闭分层编译的情况下Java 虚拟机将直接采用 C2。 如果你希望只是用 C1那么你可以在打开分层编译的情况下使用参数 -XX:TieredStopAtLevel1。在这种情况下Java 虚拟机会在解释执行之后直接由 1 层的 C1 进行编译。 1.2如何判断热点代码 在运行过程中会被即时编译的“热点代码” 有两类即 1.被多次调用的方法 2.被多次执行的循环体 对于第一种编译器会将整个方法作为编译对象这也是标准的JIT 编译方式。对于第二种是由循环体出发的但是编译器依然会以整个方法而不是单独的循环体作为编译对象因为发生在方法执行过程中称为栈上替换On Stack Replacement简称为 OSR 编译即方法栈帧还在栈上方法就被替换了。 1.2.1如何找到热点代码 判断一段代码是否是热点代码是不是需要触发即时编译这样的行为称为热点探测Hot Spot Detection探测算法有两种分别如下 基于采样的热点探测Sample Based Hot Spot Detection 虚拟机会周期的对各个线程栈顶进行检查如果某些方法经常出现在栈顶这个方法就是“热点方法”。好处是实现简单、高效很容易获取方法调用关系。缺点是很难确认方法的 reduce容易受到线程阻塞或其他外因扰乱。 基于计数器的热点探测Counter Based Hot Spot Detection 为每个方法甚至是代码块建立计数器执行次数超过阈值就认为是“热点方法”。优点是统计结果精确严谨。缺点是实现麻烦不能直接获取方法的调用关系。 HotSpot 使用的是第二种——基于计数器的热点探测并且有两类计数器方法调用计数器Invocation Counter 和回边计数器Back Edge Counter 。 这两个计数器都有一个确定的阈值超过后便会触发 JIT 编译。 1.2.2java两大计数器 (1)首先是方法调用计数器 。 Client 模式下默认阈值是 1500 次在 Server 模式下是 10000次这个阈值可以通过 -XXCompileThreadhold 来人为设定。如果不做任何设置方法调用计数器统计的并不是方法被调用的绝对次数而是一个相对的执行频率即一段时间之内的方法被调用的次数。当超过一定的时间限度如果方法的调用次数仍然不足以让它提交给即时编译器编译那么这个方法的调用计数器就会被减少一半这个过程称为方法调用计数器热度的衰减Counter Decay而这段时间就成为此方法的统计的半衰周期 Counter Half Life Time。进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的可以使用虚拟机参数 -XXCounterHalfLifeTime 参数设置半衰周期的时间单位是秒。整个 JIT 编译的交互过程如下图。 2.第二个回边计数器  作用是统计一个方法中循环体代码执行的次数在字节码中遇到控制流向后跳转的指令称为“回边” Back Edge 。显然建立回边计数器统计的目的就是为了触发 OSR 编译。 关于这个计数器的阈值 HotSpot 提供了 -XXBackEdgeThreshold 供用户设置但是当前的虚拟机实际上使用了 -XXOnStackReplacePercentage 来简介调整阈值计算公式如下 在 Client模式下 公式为 方法调用计数器阈值CompileThresholdX OSR 比率OnStackReplacePercentage/ 100 。其中 OSR 比率默认为 933那么回边计数器的阈值为 13995。 在 Server 模式下公式为 方法调用计数器阈值Compile ThreasholdX OSR 比率(OnStackReplacePercentage) - 解释器监控比率InterpreterProfilePercent/100。   其中 onStackReplacePercentage 默认值为 140InterpreterProfilePercentage 默认值为 33如果都取默认值那么 Server 模式虚拟机回边计数器阈值为10700。 与方法计数器不同回边计数器没有计数热度衰减的过程因此这个计数器统计的就是该方法循环执行的绝对次数。当计数器溢出的时候它还会把方法计数器的值也调整到溢出状态这样下次再进入该方法的时候就会执行标准编译过程。 可以看到决定一个方法是否为热点代码的因素有两个方法的调用次数、循环回边的执行次数。即时编译便是根据这两个计数器的和来触发的。为什么 Java 虚拟机需要维护两个不同的计数器呢 1.3OSR 编译不重要 实际上除了以方法为单位的即时编译之外Java 虚拟机还存在着另一种以循环为单位的即时编译叫做 On-Stack-ReplacementOSR编译。循环回边计数器便是用来触发这种类型的编译的。 OSR 实际上是一种技术它指的是在程序执行过程中动态地替换掉 Java 方法栈桢从而使得程序能够在非方法入口处进行解释执行和编译后的代码之间的切换。也就是说我只要遇到回边指令我就可以触发执行切换。 在不启用分层编译的情况下触发 OSR 编译的阈值是由参数 -XX:CompileThreshold 指定的阈值的倍数。 该倍数的计算方法为 (OnStackReplacePercentage -InterpreterProfilePercentage)/100 其中 -XX:InterpreterProfilePercentage 的默认值为 33当使用 C1 时 -XX:OnStackReplacePercentage 为 933当使用 C2 时为 140。 也就是说默认情况下C1 的 OSR 编译的阈值为 13500而 C2 的为 10700。 在启用分层编译的情况下触发 OSR 编译的阈值则是由参数 -XX:TierXBackEdgeThreshold 指定的阈值乘以系数。 OSR 编译在正常的应用程序中并不多见。它只在基准测试时比较常见因此并不需要过多了解。 那么这些即时编译器编译后的代码放哪呢 1.3Code Cache JVM生成的native code存放的内存空间称之为Code CacheJIT编译、JNI等都会编译代码到native code其中JIT生成的native code占用了Code Cache的绝大部分空间他是属于非堆内存的。 简而言之JVM Code Cache 代码缓存是JVM存储编译成本机代码的字节码的区域。我们将可执行本机代码的每个块称为 nmethod 。 nmethod 可能是一个完整的或内联的Java方法。 即时JIT编译器是代码缓存区的最大消费者。这就是为什么一些开发人员将此内存称为JIT代码缓存。 1.3.1Code Cache的优化 代码缓存的大小是固定的。一旦它满了JVM就不会编译任何额外的代码因为JIT编译器现在处于关闭状态。此外我们将收到“ CodeCache is full… The compiler has been disabled ”警告消息。因此我们的应用程序的性能最终会下降。为了避免这种情况我们可以使用以下大小选项调整代码缓存 InitialCodeCacheSize –初始代码缓存大小默认为160K ReservedCodeCacheSize –默认最大大小为48MB CodeCacheExpansionSize –代码缓存的扩展大小32KB或64KB 增加ReservedCodeCacheSize可能是一个解决方案但这通常只是一个临时解决办法。 幸运的是JVM提供了一个 UseCodeCache 刷新选项来控制代码缓存区域的刷新。其默认值为false。当我们启用它时它会在满足以下条件时释放占用的区域 代码缓存已满如果该区域的大小超过某个阈值则会刷新该区域 自上次清理以来已过了特定的时间间隔 预编译代码不够热。对于每个编译的方法JVM都会跟踪一个特殊的热度计数器。如果此计数器的值小于计算的阈值JVM将释放这段预编译代码 1.3.2Code Cache的查看 为了监控Code Cache代码缓存的使用情况我们需要跟踪当前正在使用的内存的大小。 要获取有关代码缓存使用情况的信息我们可以指定 –XX:PrintCodeCache JVM选项。运行应用程序后我们将看到类似的输出 或者直接设置 -XX:ReservedCodeCacheSize3000k然后重启 让我们看看这些值的含义 输出中的大小显示内存的最大大小与ReservedCodeCacheSize相同 used 是当前正在使用的内存的实际大小 max_used 是已使用的最大尺寸 free是尚未占用的剩余内存 1.4JDK9中的分段代码缓存 从Java9开始JVM将代码缓存分为三个不同的段每个段都包含特定类型的编译代码。更具体地说有三个部分 -XX:nonNMethoddeHeapSize -XX:ProfiledCodeHeapSize -XX:nonprofiedCodeHeapSize 这种新结构以不同的方式处理各种类型的编译代码从而提高了整体性能。 例如将短命编译代码与长寿命代码分离可以提高方法清理器的性能——主要是因为它需要扫描更小的内存区域 2.AOT和Graal VM 在Java9中引入了AOT(Ahead-Of-Time)编译器 即时编译器是在程序运行过程中将字节码翻译成机器码。而AOT是在程序运行之前将字节码转换为机器码 优势这样不需要在运行过程中消耗计算机资源来进行即时编译 劣势AOT 编译无法得知程序运行时的信息因此也无法进行基于类层次分析的完全虚方法内联或者基于程序 profile 的投机性优化并非硬性限制我们可以通过限制运行范围或者利用上一次运行的程序 profile 来绕开这两个限制 3.Graal VM 官网 https://www.oracle.com/tools/graalvm-enterprise-edition.html GraalVM core features include:  - GraalVM Native Image, available as an early access feature –– allows scripted applications to be compiled ahead of time into a native machine-code binary  - GraalVM Compiler –– generates compiled code to run applications on a JVM, standalone, or embedded in another system - Polyglot Capabilities –– supports Java, Scala, Kotlin, JavaScript, and Node.js - Language Implementation Framework –– enables implementing any language for the GraalVM environment - LLVM Runtime–– permits native code to run in a managed environment in GraalVM Enterprise 在Java10中新的JIT编译器Graal被引入 它是一个以Java为主要编程语言面向字节码的编译器。跟C实现的C1和C2相比模块化更加明显也更加容易维护。 Graal既可以作为动态编译器在运行时编译热点方法也可以作为静态编译器实现AOT编译。 除此之外它还移除了编程语言之间的边界并且支持通过即时编译技术将混杂了不同的编程语言的代码编译到同一段二进制码之中从而实现不同语言之间的无缝切换。 4.重新认知JVM 之前我们画过一张图是从Class文件到类装载器再到运行时数据区的过程。 现在咱们把这张图不妨丰富完善一下展示了JVM的大体物理结构图。 JVM Architecture https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html  5.JVM常用命令 jinfo 实时查看和调整JVM配置参数 查看用法 jinfo -flag name PID     查看某个java进程的name属性的值 jinfo -flag MaxHeapSize PID  jinfo -flag UseG1GC PID 修改参数只有被标记为manageable的flags可以被实时修改 jinfo -flag [|-] PID jinfo -flag namevalue PID 查看曾经赋过值的一些参数 jinfo -flags PID jstat查看虚拟机性能统计信息 查看类装载信息 jstat -class PID 1000 10   查看某个java进程的类装载信息每1000毫秒输出一次共输出10次 查看垃圾收集信息 jstat -gc PID 1000 10 jstack查看线程堆栈信息 jstack PID 排查死锁案例 //运行主类 public class DeadLockDemo {public static void main(String[] args){DeadLock d1new DeadLock(true);DeadLock d2new DeadLock(false);Thread t1new Thread(d1);Thread t2new Thread(d2);t1.start();t2.start();} } //定义锁对象 class MyLock{public static Object obj1new Object();public static Object obj2new Object(); } //死锁代码 class DeadLock implements Runnable{private boolean flag;DeadLock(boolean flag){this.flagflag;}public void run() {if(flag) {while(true) {synchronized(MyLock.obj1) {System.out.println(Thread.currentThread().getName()----if获得obj1锁);synchronized(MyLock.obj2) {System.out.println(Thread.currentThread().getName()----if获得obj2锁);}}}}else {while(true){synchronized(MyLock.obj2) {System.out.println(Thread.currentThread().getName()----否则获得obj2锁);synchronized(MyLock.obj1) {System.out.println(Thread.currentThread().getName()----否则获得obj1锁);}}}}} }jstack分析 jmap,生成堆转储快照 打印出堆内存相关信息 jmap -heap PID jinfo -flag UsePSAdaptiveSurvivorSizePolicy 35352 -XX:SurvivorRatio8 dump出堆内存相关信息 jmap -dump:formatb,fileheap.hprof PID 要是在发生堆内存溢出的时候能自动dump出该文件就好了 一般在开发中JVM参数可以加上下面两句这样内存溢出时会自动dump出该文件 -XX:HeapDumpOnOutOfMemoryError     -XX:HeapDumpPathheap.hprof 设置堆内存大小: -Xms20M -Xmx20M 启动然后访问localhost:9090/heap使得堆内存溢出
http://www.huolong8.cn/news/96034/

相关文章:

  • 广州专业做外贸网站建设哈尔滨菜牌制作
  • 高端网站制作上海站霸科技wordpress 谷歌加速插件
  • 网站开发常用的数据库重庆品牌设计公司排行
  • 怎么根据已有网站做新网站仿wordpress大学模板
  • 怎么给网站备案网页制作图
  • 建视频网站软件项目管理的过程
  • 网站开发在线杭州互联网企业排名
  • 做细分行业信息网站重庆知名网站建设公司
  • 厚街网站建设费用影楼网站怎么做
  • 适合做手机主页的网站公司网上注册
  • 塘厦理工学校百度seo优化分析
  • 姜堰区住房和城乡建设局网站广州翼讯资讯科技有限公司 网站
  • 网站主持人制作网站代言人php网站如何导入数据库
  • python微信网站开发四川省建筑人才网个人中心
  • 怎么做磁力网站做推文加入视频的网站
  • 网站运行平台包括广告设计与制作专业大学排名
  • 做几何图形和网站wordpress coshtmlcache
  • 做网站设计怎么提升本单位二级网站建设管理制度
  • 深圳专业专业网站设计公司wordpress 无法发送邮件
  • 沈阳做企业网站公众号开发教程零基础
  • 建设银行官方网站app下载做ppt的素材网站
  • 用discuz怎样做网站wordpress代码执行漏洞
  • 怎么做班级网站建设厅官方网站下载专区
  • 诸城网站做的好的附近装修设计公司
  • 宁波北仑网站网页建设网站的投票 计数模块怎么做
  • 网站建设需要那些人才网站没有问题但是一直做不上首页
  • wordpress 错误上海外贸seo
  • 纯代码添加wordpress网站底部导航郑州网络科技公司有哪些
  • 亚马逊欧洲站wordpress 下载附件
  • 深圳网站建设培训机构网站建设期末作业要求