侧边栏壁纸
  • 累计撰写 57 篇文章
  • 累计创建 10 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

5、调优案例分析与实战

yilee
2023-04-04 / 0 评论 / 0 点赞 / 37 阅读 / 0 字
温馨提示:
本文最后更新于2024-05-31,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

第五章 调优案例分析与实战*

5.1 概述

通过实践使读者获得故障处理和调优的经验。

5.2 案例分析

  1. 高性能硬件上的程序部署策略

    有两种方式可供选择:

    • 通过64 位JDK 来使用大内存。
    • 使用若干个32 位虚拟机建立逻辑集群来利用硬件资源。

    使用64 位JDK 来管理大内存会面临以下困难:

    • 内存回收导致的长时间停顿。
    • 现阶段, 64 位JDK 的性能测试结果普遍低于32 位JDK 。
    • 需要保证程序足够稳定,因为这种应用要是产生堆溢出几乎就无法产生堆转储快照(因为要产生十几GB 乃至更大的Dump 文件),哪怕产生了快照也几乎无法进行分析。
    • 相同程序在64 位JDK 消耗的内存一般比32 位JDK 大,这是由于指针膨胀,以及数据类型对齐补白等因素导致的。

    ​ 对于用户交互性强、对停顿时间敏感的系统,可以给Java 虚拟机分配超大堆的前提是有把握把应用程序的Full GC 频率控制得足够低,至少要低到不会影响用户使用,依次来保持内存可用空间在一个稳定的水平。

    使用若干个32 位虚拟机建立逻辑集群来利用硬件资源会面临以下困难:

    • 尽量避免节点竞争全局的资源, 最典型的就是磁盘竞争,各个节点如果同时访问某个磁盘文件的话(尤其是并发写操作容易出现问题),很容易导致IO 异常。
    • 很难最高效率地利用某些资源池, 譬如连接池,一般都是在各个节点建立自己独立的连接池,这样有可能导致一些节点池满了而另外一些节点仍有较多空余。尽管可以使用集中式的JNDI ,但这个有一定复杂性并且可能带来额外的性能开销。
    • 各个节点仍然不可避免地受到 32 位的内存限制,在32 位Windows 平台中每个进程只能使用2GB 的内存,考虑到堆以外的内存开销,堆一般最多只能开到l.5GB 。
    • 大量使用本地缓存(如大量使用HashMap 作为K/V 缓存)的应用,在逻辑集群中会造成较大的内存浪费,因为每个逻辑节点上都有一份缓存,这时候可以考虑把本地缓存改为集中式缓存。
  2. 集群间同步导致的内存溢出(P135)

    ​ 本案例的缺陷是这一类被集群共享的数据要使用类似JBossCac he 这种集群缓存来同步的话,可以允许读操作频繁,因为数据在本地内存有一份副本,读取的动作不会耗费多少资源,但不应当有过于频繁的写操作,那样会带来很大的网络同步的开销。

  3. 堆外内存导致的溢出错误

    ​ 除了Java 堆和永久代之外,下面这些区域还会占用较多的内存,这里所有的内存总和受到操作系统进程最大内存的限制。

    • Direct Memory:可通过 -XX : MaxDirectMemorySize 调整大小,内存不足时抛出 OutOfMemoryError 或者 OutOfMemoryError : Direct buffer memoy。
    • 线程堆枝:可通过 -Xss 调整大小,内存不足时抛出 StackOverflowError (纵向无法分配,即无法分配新的找帧)或者 OutOfMemoryError: unable to create new native thread(横向无法分配,即无法建立新的线程) 。
    • Socket 缓存区: 每个Socket 连接都Receive 和Send 两个缓存区,分别占大约37KB和25阻内存,连接多的话这块内存占用也比较可观。如果无法分配,则可能会抛出 IOException: Too many open files 异常。
    • JNI 代码:如果代码中使用JNI 调用本地库,那本地库使用的内存也不在堆中。
    • 虚拟机和GC :虚拟机、GC 的代码执行也要消耗一定的内存。
  4. 外部命令导致系统缓慢(P138)

  5. 服务器JVM 进程崩溃(P138)

  6. 不恰当数据结构导致内存占用过大(P139)

  7. 自Windows 虚拟内存导致的长时闽停顿(P141)

5.3 实战: Eclipse 运行速度调优(P142)

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区