1
2
3
4
5
6
7
8
9
10
11
12
13
14 package chapters.appenders;
15
16 import java.io.FileWriter;
17 import java.io.IOException;
18
19 import org.slf4j.Logger;
20
21 import ch.qos.logback.classic.LoggerContext;
22 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
23 import ch.qos.logback.classic.spi.ILoggingEvent;
24 import ch.qos.logback.core.FileAppender;
25 import ch.qos.logback.core.util.StatusPrinter;
26
27 public class IOPerformance extends Thread {
28 static String MSG = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890";
29 static String LOG_FILE;
30 public static String PARALLEL_FILE;
31
32 static int NUM_THREADS = 1;
33 static long l;
34 long len;
35 boolean immediateFlush;
36 Logger logger;
37 LoggerContext context;
38 double throughput;
39
40 public IOPerformance(boolean _immediateFlush, long _len) {
41 this.len = _len;
42 this.immediateFlush = _immediateFlush;
43 context = new LoggerContext();
44 logger = context.getLogger("logger-" + getName());
45
46
47
48 FileAppender<ILoggingEvent> fa = new FileAppender<ILoggingEvent>();
49 fa.setName("FILE");
50 PatternLayoutEncoder pa = new PatternLayoutEncoder();
51 pa.setPattern("%r %5p %c [%t] - %m%n");
52 pa.setContext(context);
53 pa.start();
54 fa.setEncoder(pa);
55
56 fa.setFile(LOG_FILE);
57 fa.setAppend(true);
58 fa.setContext(context);
59 fa.start();
60
61 ((ch.qos.logback.classic.Logger) logger).addAppender(fa);
62
63 StatusPrinter.print(context);
64 }
65
66 public static void main(String[] argv) throws Exception {
67 if (argv.length != 3) {
68 usage("Wrong number of arguments.");
69 }
70
71 l = Integer.parseInt(argv[0]);
72 LOG_FILE = argv[1];
73 PARALLEL_FILE = argv[2];
74
75
76
77 perfCase(true, l);
78
79
80
81 perfCase(false, l);
82
83
84
85 }
86
87 static void usage(String msg) {
88 System.err.println(msg);
89 System.err.println("Usage: java " + IOPerformance.class.getName() + " runLength logFile otherFile\n"
90 + " runLength (integer) the number of logs to generate perthread\n" + " logFile path to a logFile\n"
91 + " otherFile path to a second file\n");
92 System.exit(1);
93 }
94
95 static void perfCase(boolean immediateFlush, long len) throws Exception {
96 IOPerformance[] threads = new IOPerformance[NUM_THREADS];
97 OtherIO otherIOThread = new OtherIO();
98 otherIOThread.start();
99
100
101 for (int i = 0; i < NUM_THREADS; i++) {
102 threads[i] = new IOPerformance(immediateFlush, len);
103 }
104
105
106 for (int i = 0; i < NUM_THREADS; i++) {
107 threads[i].start();
108 }
109
110
111 double sum = 0;
112
113 for (int i = 0; i < NUM_THREADS; i++) {
114 threads[i].join();
115 sum += threads[i].throughput;
116 }
117
118
119 otherIOThread.interrupted = true;
120 otherIOThread.join();
121
122 System.out.println("On total throughput of " + (sum) + " logs per microsecond.");
123 System.out.println("------------------------------------------------");
124 }
125
126 public void run() {
127
128 long before = System.nanoTime();
129
130 for (int i = 0; i < len; i++) {
131 logger.debug(MSG);
132 }
133
134 throughput = (len * 1.0) / ((System.nanoTime() - before) / 1000);
135 System.out.println(getName() + ", immediateFlush: " + immediateFlush + ", throughput: " + throughput + " logs per microsecond.");
136 }
137 }
138
139 class OtherIO extends Thread {
140 public boolean interrupted = false;
141 public int counter = 0;
142
143 public void run() {
144 long before = System.nanoTime();
145 try {
146 FileWriter fw = new FileWriter(IOPerformance.PARALLEL_FILE, true);
147
148 while (!interrupted) {
149 counter++;
150 fw.write("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
151 fw.flush();
152 }
153 } catch (IOException e) {
154 e.printStackTrace();
155 }
156
157 double tput = (counter * 1.0) / (System.nanoTime() - before);
158 System.out.println("Counter thread " + getName() + " incremented counter by " + tput + " per nanosecond.");
159 }
160 }