Perfomance penalty of `javautilStack` » Histórico » Versión 2
Federico Vera, 2018-07-09 17:52
1 | 1 | Federico Vera | # Perfomance penalty of `java.util.Stack` |
---|---|---|---|
2 | 2 | Federico Vera | |
3 | This is copy of the original [#26](https://github.com/fasseg/exp4j/issues/26) discussion |
||
4 | |||
5 | I've been profiling `exp4j` in particular `Expression.evaluate()`, from the profiling I gathered the following data (using Netbeans profiler): |
||
6 | |||
7 | ``` |
||
8 | Using Stack 100.00% |
||
9 | |||
10 | evaluate() 19633 100.00% |
||
11 | Total Stack 10900 55.52% |
||
12 | Stack.pop() 5219 26.58% |
||
13 | Stack.push() 3361 17.12% |
||
14 | Double.valueOf() 2320 11.82% |
||
15 | HashMap.get() 1479 7.53% |
||
16 | ----------------------------------- |
||
17 | Using LinkedList 85.48% |
||
18 | |||
19 | evaluate() 16782 100.00% |
||
20 | Total LinkedList 8938 53.26% |
||
21 | LinkedList.push() 3670 21.87% |
||
22 | LinkedList.pop() 2705 16.12% |
||
23 | Double.valueOf() 2563 15.27% |
||
24 | HashMap.get() 1493 8.90% |
||
25 | ----------------------------------- |
||
26 | Using ArrayStack 46.45% |
||
27 | |||
28 | evaluate() 9120 100.00% |
||
29 | Total ArrayStack 971 10.65% |
||
30 | ArrayStack.push() 590 6.47% |
||
31 | ArrayStack.pop() 381 4.18% |
||
32 | HashMap.get() 1452 15.92% |
||
33 | ``` |
||
34 | |||
35 | The results show that most of the time used by `Expression.evaluate()` is wasted on the use of `java.util.Stack` which is backed by `java.util.Vector`. |
||
36 | I tested again using `java.util.LinkedList` which can be used as a drop in replacement for `java.util.stack`, it shows some improvements (~15%) but the boxing/unboxing process still takes up a lot of time. |
||
37 | Finally I've created a simple `ArrayStack` class that works with an array of doubles directly and doesn't need to box/unbox nor to adapt the methods from `java.util.Vector` to `push()` and `pop()`. The final result is that the `Expression.evaluate()` uses less than 50% of the time. |
||
38 | |||
39 | About the table: |
||
40 | The second column of the table is the total time in _ms_ used by the method in 1M excecutions. |
||
41 | |||
42 | The profiled code was: |
||
43 | |||
44 | ``` java |
||
45 | public class Test { |
||
46 | static final String EXPRESSION = "log(x) - y * sqrt(x^cos(y)) " |
||
47 | + "+ 43 / 9 * sin(x) - 3 ^ (-3)"; |
||
48 | public static void main(String[] args) { |
||
49 | final Expression expression = new ExpressionBuilder(EXPRESSION) |
||
50 | .variables("x", "y") |
||
51 | .build(); |
||
52 | Random rnd = new Random(); |
||
53 | double val = 0; |
||
54 | int count = 0; |
||
55 | while (count < 1000000) { |
||
56 | expression.setVariable("x", rnd.nextDouble()); |
||
57 | expression.setVariable("y", rnd.nextDouble()); |
||
58 | val += expression.evaluate(); |
||
59 | count++; |
||
60 | } |
||
61 | System.out.println(val); |
||
62 | } |
||
63 | } |
||
64 | ``` |
||
65 | |||
66 | Looking forward now most of the time seems to be used retrieving the variable values. |