我正在评估Chronicle Queue在我们软件中的使用情况,我必须做错事 我有一个appender,会很快写出约650k条目。之后它停止了,此时内存已经飙升到最大允许值,最终命中OutOfMemory。
这是我的代码:
final class LogEntryOutput implements WriteBytesMarshallable
{
private final int maxMessageSize;
private TLogEntry logEntry;
LogEntryOutput(final int maxMessageSize)
{
this.maxMessageSize = maxMessageSize;
}
public void setMarshallable(final TLogEntry logEntry)
{
this.logEntry = logEntry;
}
@Override
@SuppressWarnings({"rawtypes", "No way to provide generic type and override WriteBytesMarshallable."})
public void writeMarshallable(final BytesOut bytes)
{
bytes.writeLong(this.logEntry.getSessionId());
bytes.writeInt(this.logEntry.getLogLevel());
bytes.writeInt(this.logEntry.getSecurityLevel());
bytes.writeLong(this.logEntry.getPosixTimestamp());
// Limit size of string messages.
final int messageSize = Math.min(this.logEntry.getMessage().length(), this.maxMessageSize);
// Write message length
bytes.writeStopBit((long)messageSize);
// Write message bytes.
bytes.write(this.logEntry.getMessage(), 0, messageSize);
}
}
final TLogEntry entry = new TLogEntry();
entry.setSessionId(321234L);
entry.setLogLevel(77);
entry.setSecurityLevel(1234);
entry.setPosixTimestamp(6141234321L);
entry.setMessage("This is a test message for the system................................ A");
final LogEntryOutput output = new LogEntryOutput(1024);
output.setMarshallable(entry);
final ChronicleQueue queue = SingleChronicleQueueBuilder.binary(config.getQueueDirectory())
.rollCycle(RollCycles.HOURLY)
.build();
final ExcerptAppender appender = queue.acquireAppender();
for (int j = 0; j < 100; ++j)
{
for (int i = 0; i < 10000; ++i)
{
appender.writeBytes(output);
}
System.out.println((j+1) * 10000);
Jvm.pause(100L);
}
queue.close();
这是在带有64位JVM的Windows 7 x64中运行,使用:-Xmx1024m
我可能做错了什么想法?
编辑:我有其他信息。在内存峰值之后,我拍摄了对象分配的快照。很多对象数组等。 当我收到OOM错误时,堆栈跟踪。
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.concurrent.ConcurrentLinkedQueue.offer(ConcurrentLinkedQueue.java:328)
at java.util.concurrent.ConcurrentLinkedQueue.add(ConcurrentLinkedQueue.java:297)
at net.openhft.chronicle.core.ReferenceCounter.recordRelease(ReferenceCounter.java:88)
at net.openhft.chronicle.core.ReferenceCounter.release(ReferenceCounter.java:79)
at net.openhft.chronicle.bytes.NativeBytesStore.release(NativeBytesStore.java:267)
at net.openhft.chronicle.bytes.MappedBytes.acquireNextByteStore(MappedBytes.java:186)
at net.openhft.chronicle.bytes.MappedBytes.peekVolatileInt(MappedBytes.java:388)
at net.openhft.chronicle.wire.AbstractWire.readMetaDataHeader(AbstractWire.java:222)
at net.openhft.chronicle.queue.impl.single.SCQIndexing.arrayForAddress(SCQIndexing.java:190)
at net.openhft.chronicle.queue.impl.single.SCQIndexing.sequenceForPosition(SCQIndexing.java:492)
at net.openhft.chronicle.queue.impl.single.SingleChronicleQueueStore.sequenceForPosition(SingleChronicleQueueStore.java:272)
at net.openhft.chronicle.queue.impl.single.SingleChronicleQueueExcerpts$StoreAppender.checkWritePositionHeaderNumber(SingleChronicleQueueExcerpts.java:339)
at net.openhft.chronicle.queue.impl.single.SingleChronicleQueueExcerpts$StoreAppender.writingDocument(SingleChronicleQueueExcerpts.java:267)
at net.openhft.chronicle.wire.MarshallableOut.writingDocument(MarshallableOut.java:55)
at net.openhft.chronicle.queue.impl.single.SingleChronicleQueueExcerpts$StoreAppender.writeBytes(SingleChronicleQueueExcerpts.java:117)
at com.selinc.winchester.ledger.writer.harness.queue.LogEntryConsumers$LogEntryChronicle.accept(LogEntryConsumers.java:78)
at com.selinc.winchester.ledger.writer.harness.queue.LogEntryConsumers$LogEntryChronicle.accept(LogEntryConsumers.java:45)
at com.selinc.winchester.ledger.writer.harness.queue.LogEntryConsumersTest.test(LogEntryConsumersTest.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:643)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
答案 0 :(得分:1)
Chronicle Queue有一些额外的检查来检测使用public class ATest {
static class TLogEntry {
private long sessionId;
private int logLevel;
private int securityLevel;
private long posixTimestamp;
private CharSequence message;
public long getSessionId() {
return sessionId;
}
public void setSessionId(long sessionId) {
this.sessionId = sessionId;
}
public int getLogLevel() {
return logLevel;
}
public void setLogLevel(int logLevel) {
this.logLevel = logLevel;
}
public int getSecurityLevel() {
return securityLevel;
}
public void setSecurityLevel(int securityLevel) {
this.securityLevel = securityLevel;
}
public long getPosixTimestamp() {
return posixTimestamp;
}
public void setPosixTimestamp(long posixTimestamp) {
this.posixTimestamp = posixTimestamp;
}
public CharSequence getMessage() {
return message;
}
public void setMessage(CharSequence message) {
this.message = message;
}
}
static class LogEntryOutput implements WriteBytesMarshallable {
private final int maxMessageSize;
private TLogEntry logEntry;
LogEntryOutput(final int maxMessageSize) {
this.maxMessageSize = maxMessageSize;
}
public void setMarshallable(final TLogEntry logEntry) {
this.logEntry = logEntry;
}
@Override
@SuppressWarnings({"rawtypes", "No way to provide generic type and override WriteBytesMarshallable."})
public void writeMarshallable(final BytesOut bytes) {
bytes.writeLong(this.logEntry.getSessionId());
bytes.writeInt(this.logEntry.getLogLevel());
bytes.writeInt(this.logEntry.getSecurityLevel());
bytes.writeLong(this.logEntry.getPosixTimestamp());
// Limit size of string messages.
final int messageSize = Math.min(this.logEntry.getMessage().length(), this.maxMessageSize);
// Write message length
bytes.writeStopBit((long) messageSize);
// Write message bytes.
bytes.write(this.logEntry.getMessage(), 0, messageSize);
}
}
@Test
public void test() {
final TLogEntry entry = new TLogEntry();
entry.setSessionId(321234L);
entry.setLogLevel(77);
entry.setSecurityLevel(1234);
entry.setPosixTimestamp(6141234321L);
entry.setMessage("This is a test message for the system................................ A");
final LogEntryOutput output = new LogEntryOutput(1024);
output.setMarshallable(entry);
final ChronicleQueue queue = SingleChronicleQueueBuilder.binary(
OS.TARGET + "/test-" + System.nanoTime())
.rollCycle(RollCycles.HOURLY)
.build();
final ExcerptAppender appender = queue.acquireAppender();
Jvm.setExceptionHandlers(Slf4jExceptionHandler.FATAL, Slf4jExceptionHandler.WARN, Slf4jExceptionHandler.WARN);
for (int j = 0; j < 1000; ++j) {
for (int i = 0; i < 10000; ++i) {
appender.writeBytes(output);
}
System.out.println((j + 1) * 10000);
// Jvm.pause(100L);
}
queue.close();
}
}
打开的内存泄漏。如果您运行这些额外的检查,队列确实会减慢大约90,000条消息。如果你关闭断言,你会让它运行更长时间。
在具有8 GB内存的Windows笔记本电脑上,在5.5秒内运行10,000,000个条目,关闭断言
它还在66秒内创造了1亿的记录。
HttpClient / HttpWebRequest