为什么您的软件会老化?

软件老化指的是由于资源耗尽、碎片和错误积累导致的性能下降或系统崩溃。文章通过实例解释了内存泄漏、锁争用、未关闭的文件句柄等问题如何导致软件老化,特别是针对Java应用。内存泄漏是最常见的问题,现代JVM虽然有所缓解,但大量交换仍可能导致性能严重下降。
摘要由CSDN通过智能技术生成

我最近偶然发现了术语软件老化。 我对此主题的最初想法不太积极,尤其是在阅读了Wikipedia定义之后 。 唯一的流行语是我脑海中唯一能引起共鸣的东西。 但是,在深入研究这个概念之后,我开始有所不同。 即使是我们自己的产品,本质上也可以为软件老化的结果提供保护。 因此,我认为一些概念值得与您分享。

但是,让我们先从维基百科关于该主题的观点开始:

软件老化是指由于操作系统资源用尽,碎片和错误累积而导致的性能逐步下降或软件系统突然挂起/崩溃。

这个定义很无聊。 但是我想大家都记得刚启动的Windows运行良好的日子。 但是在短短几天内,它变得如此缓慢,以至于唯一的解决方案就是重启。 在一年左右的时间里,您需要全新安装,因为重新启动不再对您有帮助。

重新启动和重新安装Windows是一个很好的例子,我想大多数人都可以轻松地与之联系。 甚至甚至同意David Lodge Parnas关于这个问题的看法:

程序像人一样会变老。 我们无法防止老化,但是我们可以了解其原因,采取措施限制其影响,暂时消除其造成的某些损害,并为该软件不再可用的日子做准备。 我们必须全神贯注于第一个版本,并专注于产品的长期健康。

在这句话中,先生。 Parnas还暗示,旧版应用程序更容易老化,但是无论代码库大小如何,您都可能会遭受软件老化的不同原因,例如:

  • 内存泄漏(我们目前的面包和黄油)
  • 锁争用问题
  • 未发布的文件句柄
  • 内存/交换空间膨胀
  • 资料损坏
  • 存储空间碎片
  • 舍入错误累积

由于列表过于干燥,因此我将尝试通过引用Java界的例子来增强其功能,以说明原因的相关性(或不相关性)。

内存泄漏 。 这就是我们目前的面包和黄油 –每天我都面临着数十种不同的情况,这些应用程序正遭受泄漏。 事实上,从我们目前的数千个应用程序数据集中,我们可以看到大约50%的应用程序确实包含一个应用程序。 以下示例说明了这种情况。

该程序一次读取一个数字并计算其平方值。 此实现使用原始的“缓存”来存储计算结果。 但是由于这些结果永远不会从高速缓存中读取,因此代码块表示内存泄漏。 如果我们让该程序运行并与用户互动足够长的时间,则“缓存”结果将占用大量内存。 它是老化的一个很好的样本–该程序可以在最终用户受到影响之前使用数天。

public class Calc {
  Map cache = new HashMap();

  public int square(int i) {
     int result = i * i;
     cache.put(i, result);
     return result;
  }

  public static void main(String[] args) throws Exception {
     Calc calc = new Calc();
     while (true)
        System.out.println("Enter a number between 1 and 100");
        int i = readUserInput(); //not shown
        System.out.println("Answer " + calc.square(i));
     }
  }
}

锁定争用 。 多年以来,您都必须一直处在应用程序运行良好的情况下,然后在负载小幅增加之后,您将开始面临这样的情况:线程开始在同步块后面等待,或者饿死或完全锁定。

以下示例作为案例的教科书插图。 在您启动两个试图同时运行transfer(a,b)和transfer(b,a)并导致死锁的线程之前,代码将正常工作。 再说一次,在类似情况升级为锁定线程之前,您可能会愉快地运行代码数月或数年。

class Account {
 double balance;
 int id;

 void withdraw(double amount){
    balance -= amount;
 }

 void deposit(double amount){
    balance += amount;
 }

  void transfer(Account from, Account to, double amount){
       sync(from);
       sync(to);
          from.withdraw(amount);
          to.deposit(amount);
       release(to);
       release(from);
   }
}

未发布的文件句柄 。 再次重申,我确信您在查看类似于以下内容的内容时一直在咒骂,因为其他开发人员在加载后忘记关闭资源。 在java.io.IOException之前,该代码可能已经运行了好几个月了抛出太多打开文件消息,这再次证明了老化问题。

Properties p = new Properties();
try {
   p.load(new FileInputStream(“my.properties”));
} catch (Exception ex) {}
finally {
  //no, i will NOT close the stream
 }

内存/交换空间膨胀 。 现代操作系统倾向于快速调出一段时间未使用的内存。 因此,当物理内存不足并且操作系统开始交换堆时,您可能会遇到问题。 垃圾收集使事情变得越来越糟–完整GC要求JVM遍历对象图以标识每个可访问的对象以检测垃圾。 这样做时,它将触摸应用程序堆中的每个页面,从而触发页面从内存中换入和换出。

幸运的是,由于多种原因,现代JVM中的影响有所降低,例如:

  • 大多数对象永远都不会从年轻一代中逃脱,这些新生代几乎可以保证驻留在内存中
  • 从年轻一代移出的对象往往会被频繁访问,这又倾向于将它们保留在常驻内存中。

因此,您可能已经逃脱了这一步,但是由于大量交换,我已经看到GC周期从几百毫秒延长到几十秒。 因此,我们又遇到了一个情况,由于内存膨胀,一段时间后缓存加载缓慢的行为完美的应用程序变成了可用性噩梦。

考虑以上示例–我想您可能同意我的观点,该软件确实确实像人类一样在老化。 我为我们介入救援感到非常高兴。 到目前为止,仅用于解决内存泄漏,但是我可以暗示,在我们的实验室中,我们正在酝酿许多有趣的事情。

参考: 为什么软件会老化? 由我们的JCG合作伙伴 Nikita Salnikov TarnovskiPlumbr Blog博客上获得。

翻译自: https://www.javacodegeeks.com/2013/08/why-is-your-software-aging.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值