I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit d092dd79 authored by jrandom's avatar jrandom Committed by zzz
Browse files

get rid of the really really frequent temporary object creation

parent a3ba9683
No related branches found
No related tags found
No related merge requests found
......@@ -12,24 +12,34 @@ import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
*
*/
public class BufferedStatLog implements StatLog {
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)*/
private int _flushFrequency;
private List _statFilters;
private String _lastFilters;
private BufferedWriter _out;
private String _outFile;
public BufferedStatLog(I2PAppContext 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);
_flushFrequency = 1000;
_flushFrequency = 500;
I2PThread writer = new I2PThread(new StatLogWriter(), "StatLogWriter");
writer.setDaemon(true);
writer.start();
......@@ -37,9 +47,22 @@ public class BufferedStatLog implements StatLog {
public void addData(String scope, String stat, long value, long duration) {
synchronized (_events) {
_events.add(new StatEvent(scope, stat, value, duration));
if (_events.size() > _flushFrequency)
_events.notifyAll();
_events[_eventNext].init(scope, stat, value, duration);
_eventNext = (_eventNext + 1) % _events.length;
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() {
String val = _context.getProperty("stat.logFilters");
if (val != null) {
StringTokenizer tok = new StringTokenizer(val, ",");
synchronized (_statFilters) {
_statFilters.clear();
while (tok.hasMoreTokens())
_statFilters.add(tok.nextToken().trim());
if ( (_lastFilters != null) && (_lastFilters.equals(val)) ) {
// noop
} else {
StringTokenizer tok = new StringTokenizer(val, ",");
synchronized (_statFilters) {
_statFilters.clear();
while (tok.hasMoreTokens())
_statFilters.add(tok.nextToken().trim());
}
}
_lastFilters = val;
} else {
synchronized (_statFilters) { _statFilters.clear(); }
}
......@@ -79,45 +107,58 @@ public class BufferedStatLog implements StatLog {
private class StatLogWriter implements Runnable {
private SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd HH:mm:ss.SSS");
public void run() {
List cur = new ArrayList(1000);
int writeStart = -1;
int writeEnd = -1;
while (true) {
synchronized (_events) {
if (_events.size() < _flushFrequency) {
try { _events.wait(30*1000); } catch (InterruptedException ie) {}
}
cur.addAll(_events);
_events.clear();
if (_eventNext > _lastWrite) {
if (_eventNext - _lastWrite < _flushFrequency)
try { _events.wait(30*1000); } catch (InterruptedException ie) {}
} else {
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) {
writeEvents(cur);
cur.clear();
if (writeStart != writeEnd) {
try {
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 {
updateFilters();
for (int i = 0; i < events.size(); i++) {
StatEvent evt = (StatEvent)events.get(i);
if (!shouldLog(evt.getStat())) continue;
String when = null;
synchronized (_fmt) {
when = _fmt.format(new Date(evt.getTime()));
int cur = start;
while (cur != end) {
if (shouldLog(_events[cur].getStat())) {
String when = null;
synchronized (_fmt) {
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);
_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");
cur = (cur + 1) % _events.length;
}
_out.flush();
} 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 _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;
_stat = stat;
_value = value;
_duration = duration;
_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; }
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment