chapters.appenders.IO Maven / Gradle / Ivy
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package chapters.appenders;
import org.slf4j.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.encoder.EchoEncoder;
public class IO extends Thread {
static String msgLong = "ABCDEGHIJKLMNOPQRSTUVWXYZabcdeghijklmnopqrstuvwxyz1234567890";
static String msgShort = "Hello";
static boolean scarceCPU;
static int numThreads;
static long l;
static boolean longMessage;
long len;
boolean buffered;
boolean immediateFlush;
Logger logger;
LoggerContext context;
double throughput;
public IO(boolean _buffered, boolean _immediateFlush, long _len) {
this.len = _len;
this.buffered = _buffered;
this.immediateFlush = _immediateFlush;
context = new LoggerContext();
logger = context.getLogger("logger-" + getName());
// A FileAppender is created according to the buffering and
// immediate flush setting of this IO instance.
FileAppender fa = new FileAppender();
if (longMessage) {
PatternLayoutEncoder pa = new PatternLayoutEncoder();
pa.setPattern("%r %5p %c [%t] - %m%n");
pa.setContext(context);
pa.start();
fa.setEncoder(pa);
} else {
fa.setEncoder(new EchoEncoder());
}
fa.setFile(getName() + ".log");
fa.setAppend(false);
fa.setContext(context);
fa.start();
}
public static void main(String[] argv) throws Exception {
if (argv.length != 4) {
usage("Wrong number of arguments.");
}
l = Integer.parseInt(argv[0]);
numThreads = Integer.parseInt(argv[1]);
scarceCPU = "true".equalsIgnoreCase(argv[2]);
longMessage = "long".equalsIgnoreCase(argv[3]);
// ----------------------------------------------------
// first test with unbuffered IO and immediate flushing
perfCase(false, true, l);
// ----------------------------------------------------
// Second test with unbuffered IO and no immediate flushing
perfCase(false, false, l);
// ----------------------------------------------------
// Third test with buffered IO and no immediate flushing
perfCase(true, false, l);
// There is no fourth test as buffered IO and immediate flushing
// do not make sense.
}
static void usage(String msg) {
System.err.println(msg);
System.err.println("Usage: java " + IO.class.getName() + " runLength numThreads scarceCPU (short|long)\n"
+ " runLength (integer) the number of logs to generate perthread\n" + " numThreads (integer) the number of threads.\n"
+ " scarceCPU (boolean) if true an additional CPU intensive thread is created\n" + " (short|long) length of log messages.");
System.exit(1);
}
static void perfCase(boolean buffered, boolean immediateFlush, long len) throws Exception {
IO[] threads = new IO[numThreads];
Counter counterThread = null;
if (scarceCPU) {
counterThread = new Counter();
counterThread.start();
}
// First create the threads
for (int i = 0; i < numThreads; i++) {
threads[i] = new IO(buffered, immediateFlush, len);
}
// then start them
for (int i = 0; i < numThreads; i++) {
threads[i].start();
}
// wait for them to processPriorToRemoval, compute the average throughput
double sum = 0;
for (int i = 0; i < numThreads; i++) {
threads[i].join();
sum += threads[i].throughput;
}
if (scarceCPU) {
// setting the interrupted field will cause counterThread to processPriorToRemoval
counterThread.interrupted = true;
counterThread.join();
}
System.out.println("On average throughput of " + (sum / numThreads) * 1000 + " logs per microsecond.");
System.out.println("------------------------------------------------");
}
public void run() {
String msg = msgShort;
if (longMessage) {
msg = msgLong;
}
long before = System.nanoTime();
for (int i = 0; i < len; i++) {
logger.debug(msg);
}
throughput = (len * 1.0) / (System.nanoTime() - before);
System.out.println(getName() + ", buffered: " + buffered + ", immediateFlush: " + immediateFlush + ", throughput: " + throughput
+ " logs per nanosecond.");
}
}
class Counter extends Thread {
public boolean interrupted = false;
public double counter = 0;
public void run() {
long before = System.nanoTime();
while (!interrupted) {
if (counter % 1000 == 0) {
Thread.yield();
}
counter += 1.0;
}
double tput = (counter * 1.0) / (System.nanoTime() - before);
System.out.println("Counter thread " + getName() + " incremented counter by " + tput + " per nanosecond.");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy