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()
90 + " runLength logFile otherFile\n"
91 + " runLength (integer) the number of logs to generate perthread\n"
92 + " logFile path to a logFile\n"
93 + " otherFile path to a second file\n");
94 System.exit(1);
95 }
96
97 static void perfCase(boolean immediateFlush, long len) throws Exception {
98 IOPerformance[] threads = new IOPerformance[NUM_THREADS];
99 OtherIO otherIOThread = new OtherIO();
100 otherIOThread.start();
101
102
103 for (int i = 0; i < NUM_THREADS; i++) {
104 threads[i] = new IOPerformance(immediateFlush, len);
105 }
106
107
108 for (int i = 0; i < NUM_THREADS; i++) {
109 threads[i].start();
110 }
111
112
113 double sum = 0;
114
115 for (int i = 0; i < NUM_THREADS; i++) {
116 threads[i].join();
117 sum += threads[i].throughput;
118 }
119
120
121 otherIOThread.interrupted = true;
122 otherIOThread.join();
123
124 System.out.println("On total throughput of " + (sum)
125 + " logs per microsecond.");
126 System.out.println("------------------------------------------------");
127 }
128
129 public void run() {
130
131 long before = System.nanoTime();
132
133 for (int i = 0; i < len; i++) {
134 logger.debug(MSG);
135 }
136
137 throughput = (len * 1.0) / ((System.nanoTime() - before) / 1000);
138 System.out.println(getName() + ", immediateFlush: " + immediateFlush
139 + ", throughput: " + throughput + " logs per microsecond.");
140 }
141 }
142
143 class OtherIO extends Thread {
144 public boolean interrupted = false;
145 public int counter = 0;
146
147 public void run() {
148 long before = System.nanoTime();
149 try {
150 FileWriter fw = new FileWriter(IOPerformance.PARALLEL_FILE, true);
151
152 while (!interrupted) {
153 counter++;
154 fw.write("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
155 fw.flush();
156 }
157 } catch (IOException e) {
158 e.printStackTrace();
159 }
160
161 double tput = (counter * 1.0) / (System.nanoTime() - before);
162 System.out.println("Counter thread " + getName()
163 + " incremented counter by " + tput + " per nanosecond.");
164 }
165 }