get rid of the really really frequent temporary object creation
This commit is contained in:
@ -12,24 +12,34 @@ import java.util.StringTokenizer;
|
|||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.I2PThread;
|
import net.i2p.util.I2PThread;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class BufferedStatLog implements StatLog {
|
public class BufferedStatLog implements StatLog {
|
||||||
private I2PAppContext _context;
|
private I2PAppContext _context;
|
||||||
private List _events;
|
private Log _log;
|
||||||
|
private StatEvent _events[];
|
||||||
|
private int _eventNext;
|
||||||
|
private int _lastWrite;
|
||||||
/** flush stat events to disk after this many events (or 30s)*/
|
/** flush stat events to disk after this many events (or 30s)*/
|
||||||
private int _flushFrequency;
|
private int _flushFrequency;
|
||||||
private List _statFilters;
|
private List _statFilters;
|
||||||
|
private String _lastFilters;
|
||||||
private BufferedWriter _out;
|
private BufferedWriter _out;
|
||||||
private String _outFile;
|
private String _outFile;
|
||||||
|
|
||||||
public BufferedStatLog(I2PAppContext ctx) {
|
public BufferedStatLog(I2PAppContext ctx) {
|
||||||
_context = ctx;
|
_context = ctx;
|
||||||
_events = new ArrayList(1000);
|
_log = ctx.logManager().getLog(BufferedStatLog.class);
|
||||||
|
_events = new StatEvent[1000];
|
||||||
|
for (int i = 0; i < 1000; i++)
|
||||||
|
_events[i] = new StatEvent();
|
||||||
|
_eventNext = 0;
|
||||||
|
_lastWrite = _events.length-1;
|
||||||
_statFilters = new ArrayList(10);
|
_statFilters = new ArrayList(10);
|
||||||
_flushFrequency = 1000;
|
_flushFrequency = 500;
|
||||||
I2PThread writer = new I2PThread(new StatLogWriter(), "StatLogWriter");
|
I2PThread writer = new I2PThread(new StatLogWriter(), "StatLogWriter");
|
||||||
writer.setDaemon(true);
|
writer.setDaemon(true);
|
||||||
writer.start();
|
writer.start();
|
||||||
@ -37,9 +47,22 @@ public class BufferedStatLog implements StatLog {
|
|||||||
|
|
||||||
public void addData(String scope, String stat, long value, long duration) {
|
public void addData(String scope, String stat, long value, long duration) {
|
||||||
synchronized (_events) {
|
synchronized (_events) {
|
||||||
_events.add(new StatEvent(scope, stat, value, duration));
|
_events[_eventNext].init(scope, stat, value, duration);
|
||||||
if (_events.size() > _flushFrequency)
|
_eventNext = (_eventNext + 1) % _events.length;
|
||||||
_events.notifyAll();
|
|
||||||
|
if (_eventNext == _lastWrite)
|
||||||
|
_lastWrite = (_lastWrite + 1) % _events.length; // drop an event
|
||||||
|
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("AddData next=" + _eventNext + " lastWrite=" + _lastWrite);
|
||||||
|
|
||||||
|
if (_eventNext > _lastWrite) {
|
||||||
|
if (_eventNext - _lastWrite >= _flushFrequency)
|
||||||
|
_events.notifyAll();
|
||||||
|
} else {
|
||||||
|
if (_events.length - 1 - _lastWrite + _eventNext >= _flushFrequency)
|
||||||
|
_events.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +75,17 @@ public class BufferedStatLog implements StatLog {
|
|||||||
private void updateFilters() {
|
private void updateFilters() {
|
||||||
String val = _context.getProperty("stat.logFilters");
|
String val = _context.getProperty("stat.logFilters");
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
StringTokenizer tok = new StringTokenizer(val, ",");
|
if ( (_lastFilters != null) && (_lastFilters.equals(val)) ) {
|
||||||
synchronized (_statFilters) {
|
// noop
|
||||||
_statFilters.clear();
|
} else {
|
||||||
while (tok.hasMoreTokens())
|
StringTokenizer tok = new StringTokenizer(val, ",");
|
||||||
_statFilters.add(tok.nextToken().trim());
|
synchronized (_statFilters) {
|
||||||
|
_statFilters.clear();
|
||||||
|
while (tok.hasMoreTokens())
|
||||||
|
_statFilters.add(tok.nextToken().trim());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_lastFilters = val;
|
||||||
} else {
|
} else {
|
||||||
synchronized (_statFilters) { _statFilters.clear(); }
|
synchronized (_statFilters) { _statFilters.clear(); }
|
||||||
}
|
}
|
||||||
@ -79,45 +107,58 @@ public class BufferedStatLog implements StatLog {
|
|||||||
private class StatLogWriter implements Runnable {
|
private class StatLogWriter implements Runnable {
|
||||||
private SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd HH:mm:ss.SSS");
|
private SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd HH:mm:ss.SSS");
|
||||||
public void run() {
|
public void run() {
|
||||||
List cur = new ArrayList(1000);
|
int writeStart = -1;
|
||||||
|
int writeEnd = -1;
|
||||||
while (true) {
|
while (true) {
|
||||||
synchronized (_events) {
|
synchronized (_events) {
|
||||||
if (_events.size() < _flushFrequency) {
|
if (_eventNext > _lastWrite) {
|
||||||
try { _events.wait(30*1000); } catch (InterruptedException ie) {}
|
if (_eventNext - _lastWrite < _flushFrequency)
|
||||||
}
|
try { _events.wait(30*1000); } catch (InterruptedException ie) {}
|
||||||
cur.addAll(_events);
|
} else {
|
||||||
_events.clear();
|
if (_events.length - 1 - _lastWrite + _eventNext < _flushFrequency)
|
||||||
|
try { _events.wait(30*1000); } catch (InterruptedException ie) {}
|
||||||
|
}
|
||||||
|
writeStart = (_lastWrite + 1) % _events.length;
|
||||||
|
writeEnd = _eventNext;
|
||||||
|
_lastWrite = (writeEnd == 0 ? _events.length-1 : writeEnd - 1);
|
||||||
}
|
}
|
||||||
if (cur.size() > 0) {
|
if (writeStart != writeEnd) {
|
||||||
writeEvents(cur);
|
try {
|
||||||
cur.clear();
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("writing " + writeStart +"->"+ writeEnd);
|
||||||
|
writeEvents(writeStart, writeEnd);
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("error writing " + writeStart +"->"+ writeEnd, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeEvents(List events) {
|
private void writeEvents(int start, int end) {
|
||||||
try {
|
try {
|
||||||
updateFilters();
|
updateFilters();
|
||||||
for (int i = 0; i < events.size(); i++) {
|
int cur = start;
|
||||||
StatEvent evt = (StatEvent)events.get(i);
|
while (cur != end) {
|
||||||
if (!shouldLog(evt.getStat())) continue;
|
if (shouldLog(_events[cur].getStat())) {
|
||||||
String when = null;
|
String when = null;
|
||||||
synchronized (_fmt) {
|
synchronized (_fmt) {
|
||||||
when = _fmt.format(new Date(evt.getTime()));
|
when = _fmt.format(new Date(_events[cur].getTime()));
|
||||||
|
}
|
||||||
|
_out.write(when);
|
||||||
|
_out.write(" ");
|
||||||
|
if (_events[cur].getScope() == null)
|
||||||
|
_out.write("noScope ");
|
||||||
|
else
|
||||||
|
_out.write(_events[cur].getScope() + " ");
|
||||||
|
_out.write(_events[cur].getStat()+" ");
|
||||||
|
_out.write(_events[cur].getValue()+" ");
|
||||||
|
_out.write(_events[cur].getDuration()+"\n");
|
||||||
}
|
}
|
||||||
_out.write(when);
|
cur = (cur + 1) % _events.length;
|
||||||
_out.write(" ");
|
|
||||||
if (evt.getScope() == null)
|
|
||||||
_out.write("noScope ");
|
|
||||||
else
|
|
||||||
_out.write(evt.getScope() + " ");
|
|
||||||
_out.write(evt.getStat()+" ");
|
|
||||||
_out.write(evt.getValue()+" ");
|
|
||||||
_out.write(evt.getDuration()+"\n");
|
|
||||||
}
|
}
|
||||||
_out.flush();
|
_out.flush();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
_log.error("Error writing out", ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,18 +170,18 @@ public class BufferedStatLog implements StatLog {
|
|||||||
private long _value;
|
private long _value;
|
||||||
private long _duration;
|
private long _duration;
|
||||||
|
|
||||||
public StatEvent(String scope, String stat, long value, long duration) {
|
public long getTime() { return _time; }
|
||||||
|
public String getScope() { return _scope; }
|
||||||
|
public String getStat() { return _stat; }
|
||||||
|
public long getValue() { return _value; }
|
||||||
|
public long getDuration() { return _duration; }
|
||||||
|
|
||||||
|
public void init(String scope, String stat, long value, long duration) {
|
||||||
_scope = scope;
|
_scope = scope;
|
||||||
_stat = stat;
|
_stat = stat;
|
||||||
_value = value;
|
_value = value;
|
||||||
_duration = duration;
|
_duration = duration;
|
||||||
_time = _context.clock().now();
|
_time = _context.clock().now();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTime() { return _time; }
|
|
||||||
public String getScope() { return _scope; }
|
|
||||||
public String getStat() { return _stat; }
|
|
||||||
public long getValue() { return _value; }
|
|
||||||
public long getDuration() { return _duration; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user