Skip to content

Commit

Permalink
Create MessagePack singleton provider to avoid PermGen leak.
Browse files Browse the repository at this point in the history
Prepare the MessagePack instance with a RadioMessage because generating
code for the MessagePack template registry is not thread-safe.

Before this, a new MessagePack instance got created for each processed
message which eventually lead to PermGen exhaustion. Not sure why the
generated classes haven't been garbage collected. (bug in msgpack?)

Fixes #907.
  • Loading branch information
bernd committed Jan 20, 2015
1 parent f44f6a9 commit d9d4ef8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
Expand Up @@ -30,16 +30,18 @@
import org.graylog2.plugin.inputs.MessageInput;
import org.graylog2.plugin.inputs.util.ThroughputCounter;
import org.graylog2.plugin.system.NodeId;
import org.graylog2.shared.buffers.InputBufferImpl;
import org.graylog2.shared.buffers.ProcessBuffer;
import org.graylog2.shared.buffers.processors.DecodingProcessor;
import org.graylog2.shared.bindings.providers.EventBusProvider;
import org.graylog2.shared.bindings.providers.MessagePackProvider;
import org.graylog2.shared.bindings.providers.MetricRegistryProvider;
import org.graylog2.shared.bindings.providers.NodeIdProvider;
import org.graylog2.shared.bindings.providers.ServiceManagerProvider;
import org.graylog2.shared.buffers.InputBufferImpl;
import org.graylog2.shared.buffers.ProcessBuffer;
import org.graylog2.shared.buffers.processors.DecodingProcessor;
import org.graylog2.shared.inputs.InputRegistry;
import org.graylog2.shared.stats.ThroughputStats;
import org.jboss.netty.util.HashedWheelTimer;
import org.msgpack.MessagePack;

import java.util.concurrent.Semaphore;

Expand Down Expand Up @@ -77,5 +79,7 @@ protected void configure() {
install(new FactoryModuleBuilder().build(new TypeLiteral<IOState.Factory<MessageInput>>(){}));

bind(InputRegistry.class).asEagerSingleton();

bind(MessagePack.class).toProvider(MessagePackProvider.class).in(Scopes.SINGLETON);
}
}
@@ -0,0 +1,50 @@
/**
* This file is part of Graylog2.
*
* Graylog2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Graylog2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Graylog2. If not, see <http://www.gnu.org/licenses/>.
*/

package org.graylog2.shared.bindings.providers;

import org.graylog2.plugin.RadioMessage;
import org.msgpack.MessagePack;

import javax.inject.Provider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
* MessagePack generates classes for each new instance and message type which can leak into PermGen.
*
* Must be a singleton provider!
*/
public class MessagePackProvider implements Provider<MessagePack> {
@Override
public MessagePack get() {
final MessagePack messagePack = new MessagePack();

try {
// Eagerly generate RadioMessage classes in the MessagePack object to avoid doing it on runtime.
// The generated code is thread-safe, but generating it is not.
final RadioMessage radioMessage = new RadioMessage();
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
messagePack.write(stream, radioMessage);
final byte[] bytes = stream.toByteArray();
messagePack.read(bytes, RadioMessage.class);
} catch (IOException ignore) {
}

return messagePack;
}
}

0 comments on commit d9d4ef8

Please sign in to comment.