ads1

четверг, 10 декабря 2015 г.

Why do your programs "age"?

I recently came across a term such as "aging." Initially, I thought it was just some regular nothing meaningful definition (and in this I was convinced after reading the article on Wikipedia), but when I penetrated deeper into this concept, it has seemed to me very sensible. So I thought it was worth sharing your thoughts and expertise on this topic with you.
Let's start with what Wikipedia says about the "aging":
Aging - process of continuous degradation of performance and / or sudden freezes / downs of software due to the depletion of resources, OS, fragmentation and accumulation of errors.
This definition is pretty darn boring. But I think all of you are faced with the following situation: you just put Windows, and satisfied its performance. Gradually, her work is getting slower, and to solve the problem, you must reboot. It takes a year and even a system reboot does not help, and you have to reinstall the OS again.
Restart / reinstall Windows - a great example familiar to many. David Parnas once said:
Programs, like people, get old. We can not prevent aging, but we can understand its causes, its effects are limited, temporarily repair the damage that it has caused, and prepare for the day when the program will become unsustainable. With the first release of your software you need to engage the support and improvement of the status of the product.
Parnas also mentioned that legacy software is more vulnerable to aging. Regardless of its volume, your code is likely exposed aging software caused by different causes:

memory leaks;
blocking behavior;
too many open files;
swelling of memory / swap file;
corruption of data;
fragmentation of data storage;
the accumulation of rounding errors.

Since the list is a little dry, I will try to illustrate it with the help of Java.

Memory leaks

At the moment, work with memory leaks - the main source of income of our company. We have worked with thousands of applications, and 50% of them comprise at least one drain. The following example illustrates such a case.
The program reads one number and raises it in the square, and then adds the result in the realization of primitive cache. But since the value will never be read from the cache, you can say that the memory is used for nothing, and thus, a memory leak occurs. If we run this code and allow users to work with him for a long time, the cache will eventually occupy more memory, but it can be used. Such a situation is a good example of aging - the program can work days before users begin to feel uncomfortable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
        System.out.println("Answer " + calc.square(i));
     }
  }
}

blocking behavior

We were all in a situation where the program worked fine for years, and then something happened, and the floods began stand and suffer from a lack of resources.

The following example is an excellent illustration. The following code worked fine for months to as long as someone does not start the operation at the same time transfer (a, b) and transfer (b, a). In such a case arise deadlock.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
   }
}

Unclosed files

I am sure that many of you have met such a code, cursing colleague who forgets to close after loading the resources are most needed. This code can work for months, but in the end inevitably will give java.io.IOException: Too many open files, which, again, is an excellent example of the causes of aging.

Properties p = new Properties();
try {
  p.load(new FileInputStream(my.properties));
} catch (Exception ex) {}
finally {
  // I do not want to close the flow will not close the stream
}

Inflating memory / swap

Modern operating systems often move long unused portions of the operating memory to secondary storage, and you can run into problems when physical memory would no longer be enough, and the system will begin to move its unused bits in a paging file or swap-partition, freeing up RAM for a desired operation. The situation becomes even worse when using GC - full garbage collection should bypass the garbage every available object in the object graph to find the trash. In the process, it will affect every page in a pile of applications, thereby causing continuous exchange of pages between RAM and swap file. Fortunately, modern JVM implications of this work are negligible for several reasons: most of the objects have never come out of the younger generation, which is almost guaranteed to be always in the memory; objects, transformed into the old generation, constantly turning, which means that they secured a place in memory. So what can you and managed to avoid such problems, but I've seen garbage collection took tens of seconds because of the constant exchange pages. And again we have a situation where the application is loaded lazily cache becomes impossible to use after a few months of work. Do you agree that the software tends to grow old in the same way as humans, considering the above examples? Personally, I think so.

Комментариев нет:

Отправить комментарий