1   package ch.qos.logback.classic.net;
2   
3   import java.io.IOException;
4   import java.io.ObjectOutputStream;
5   import java.net.Socket;
6   
7   import junit.framework.TestCase;
8   import ch.qos.logback.classic.net.testObjectBuilders.Builder;
9   import ch.qos.logback.classic.net.testObjectBuilders.TrivialLoggingEventBuilder;
10  import ch.qos.logback.classic.net.testObjectBuilders.MinimalSerBuilder;
11  
12  public class SerializationPerfsTest extends TestCase {
13  
14    ObjectOutputStream oos;
15  
16    int loopNumber = 10000;
17    int resetFrequency = 100;
18    int pauseFrequency = 10;
19    long pauseLengthInMillis = 20;
20  
21    /**
22     * <p>
23     * Run the test with a MockSocketServer or with a NOPOutputStream
24     * 
25     * <p>
26     * Run with external mock can be done using the ExternalMockSocketServer. It
27     * needs to be launched from a separate JVM. The ExternalMockSocketServer does
28     * not consume the events but passes through the available bytes that it is
29     * receiving.
30     * 
31     * <p>
32     * For example, with 4 test methods, you can launch the
33     * ExternalMockSocketServer this way:
34     * </p>
35     * <p>
36     * <code>java ch.qos.logback.classic.net.ExternalMockSocketServer 4</code>
37     * </p>
38     */
39    boolean runWithExternalMockServer = true;
40  
41          /**
42           * Last results:
43           * Data sent mesured in kilobytes.
44           * Avg time mesured in microsecs.
45           * 
46           * NOPOutputStream: 
47           *   |                |  Runs | Avg time | Data sent |
48           *   | MinimalObj Ext | 10000 |          |           |
49           *   | MinimalObj Ser | 10000 |          |           |
50           *   | LoggEvent Ext  | 10000 |          |           |
51           *   | LoggEvent Ser  | 10000 |          |           |
52           * 
53           * External MockServer with 45 letters-long message: on localhost
54           * (always the same message)
55           *       |                |  Runs | Avg time | Data sent |
56           *   | MinimalObj Ext | 10000 |      -   |       -   |
57           *   | MinimalObj Ser | 10000 |     74   |     248   |
58           *   | LoggEvent Ext  | 10000 |      -   |       -   |
59           *   | LoggEvent Ser  | 10000 |    156   |     835   |
60           *       pauseFrequency = 10 and pauseLengthInMillis = 20
61           *
62           * External MockServer with 45 letters-long message: on localhost
63           * (different message each time)
64           *       |                |  Runs | Avg time | Data sent |
65           *   | MinimalObj Ext | 10000 |          |           |
66           *   | MinimalObj Ser | 10000 |     73   |    1139   |
67           *   | LoggEvent Ext  | 10000 |          |           |
68           *   | LoggEvent Ser  | 10000 |    162   |    1752   |
69           *       pauseFrequency = 10 and pauseLengthInMillis = 20
70           *
71           * External MockServer with 45 letters-long message: on PIXIE
72           * (always the same message)
73           *       |                |  Runs | Avg time | Data sent |
74           *   | MinimalObj Ext | 10000 |      -   |       -   |
75           *   | MinimalObj Ser | 10000 |     29   |     248   |
76           *   | LoggEvent Ext  | 10000 |      -   |       -   |
77           *   | LoggEvent Ser  | 10000 |     42   |     835   |
78           *       pauseFrequency = 10 and pauseLengthInMillis = 20
79           *
80           * External MockServer with 45 letters-long message: on PIXIE
81           * (different message each time)
82           *       |                |  Runs | Avg time | Data sent |
83           *   | MinimalObj Ext | 10000 |          |           |
84           *   | MinimalObj Ser | 10000 |     27   |    1139   |
85           *   | LoggEvent Ext  | 10000 |          |           |
86           *   | LoggEvent Ser  | 10000 |     44   |    1752   |
87           *       pauseFrequency = 10 and pauseLengthInMillis = 20
88           *
89           */
90  
91    public void setUp() throws Exception {
92      super.setUp();
93      if (runWithExternalMockServer) {
94        oos = new ObjectOutputStream(new Socket("pixie",
95            ExternalMockSocketServer.PORT).getOutputStream());
96      } else {
97        oos = new ObjectOutputStream(new NOPOutputStream());
98      }
99    }
100 
101   public void tearDown() throws Exception {
102     super.tearDown();
103     oos.close();
104     oos = null;
105   }
106 
107   public void runPerfTest(Builder builder, String label) throws Exception {
108     // long time1 = System.nanoTime();
109 
110     // Object builtObject = builder.build(1);
111 
112     // first run for just in time compiler
113     int resetCounter = 0;
114     int pauseCounter = 0;
115     for (int i = 0; i < loopNumber; i++) {
116       try {
117         oos.writeObject(builder.build(i));
118         oos.flush();
119         if (++resetCounter >= resetFrequency) {
120           oos.reset();
121           resetCounter = 0;
122         }
123         if (++pauseCounter >= pauseFrequency) {
124           Thread.sleep(pauseLengthInMillis);
125           pauseCounter = 0;
126         }
127 
128       } catch (IOException ex) {
129         fail(ex.getMessage());
130       }
131     }
132 
133     // second run
134     Long t1;
135     Long t2;
136     Long total = 0L;
137     resetCounter = 0;
138     pauseCounter = 0;
139     // System.out.println("Beginning mesured run");
140     for (int i = 0; i < loopNumber; i++) {
141       try {
142         t1 = System.nanoTime();
143         oos.writeObject(builder.build(i));
144         oos.flush();
145         t2 = System.nanoTime();
146         total += (t2 - t1);
147         if (++resetCounter >= resetFrequency) {
148           oos.reset();
149           resetCounter = 0;
150         }
151         if (++pauseCounter >= pauseFrequency) {
152           Thread.sleep(pauseLengthInMillis);
153           pauseCounter = 0;
154         }
155       } catch (IOException ex) {
156         fail(ex.getMessage());
157       }
158     }
159     total /= 1000;
160     System.out.println(label + " : average time = " + total / loopNumber
161         + " microsecs after " + loopNumber + " writes.");
162 
163     // long time2 = System.nanoTime();
164     // System.out.println("********* -> Time needed to run the test method: " +
165     // Long.toString(time2-time1));
166   }
167 
168   // public void testWithMinimalExternalization() throws Exception {
169   // Builder builder = new MinimalExtBuilder();
170   // runPerfTest(builder, "Minimal object externalization");
171   // }
172 
173   public void testWithMinimalSerialization() throws Exception {
174     Builder builder = new MinimalSerBuilder();
175     runPerfTest(builder, "Minimal object serialization");
176   }
177 
178   // public void testWithExternalization() throws Exception {
179   // Builder builder = new LoggingEventExtBuilder();
180   // runPerfTest(builder, "LoggingEvent object externalization");
181   // }
182 
183   public void testWithSerialization() throws Exception {
184     Builder builder = new TrivialLoggingEventBuilder();
185     runPerfTest(builder, "LoggingEvent object serialization");
186   }
187 }