I am refactoring a class called ConfigNode
that stores 50 "properties". Each property is an object of its own. All properties are optional, and most of the time, many of them are not set.
Currently, the class is written so that when it is instantiated, all 50 properties are instantiated as well. When you create a million Config
objects, Java tells me I'm using 2.5 gigs of memory. When I comment out the property instantiation, Java says I'm using 300 MB.
The benchmark code I'm using is
Runtime.getRuntime().gc();
// do my stuff
Runtime.getRuntime().gc();
long memory = Runtime.getRuntime().totalMemory();
System.out.println("Memory used: " + memory / 1000000 + " MB");
So I'm thinking of rewriting the class to lazy load a property when it's accessed, but having to write something like
// This is probably not thread safe, so it could be even more verbose
public NodeProperty propOne() {
if (propOne == null) {
propOne = new NodeProperty( ... )
}
return propOne
}
And then do it for all of the properties seems kind of verbose. Is there anything in Java that can help me reduce the amount of code I have to write (and consequently, maintain)?
Here is how the NodeConfig looks like
public class NodeConfig {
public NodeProperty pVersion = new NodeProperty( "Spec Version", Status.REQUIRED, Visibility.HIDDEN);
public NodeProperty pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE );
public NodeProperty pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.HIDDEN);
// more properties
public NodeConfig() {
//
}
}
Approach 1
Here's another approach you could use given the NodeConfig
code:
public class NodeConfig {
public NodeProperty pTwoWay;
public NodeProperty pBinary;
// more properties
public NodeConfig() {
//
}
public NodeProperty getProperty(NodePropertyEnum nodeProp) {
switch(nodeProp) {
case TWO_WAY:
if (pTwoWay != null) {return pTwoWay;}
pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE );
case BINARY_MODE:
if (pBinary != null) {return pBinary;}
pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.VISIBLE);
// other cases
default:
throw new IllegalArgumentException();
}
}
}
Approach 2
Looks like a case for Singleton
design pattern. Rather than checking for propOne
instance to be null
, it will be better if you make all Property classes singleton. Something like:
public class NodeProperty {
private static volatile NodeProperty instance = null;
private NodeProperty() {
// instantiatin logic
}
public NodeProperty getInstance() {
if(instance == null) {
synchronized(NodeProperty.class) {
if(instance==null) {
instance = new NodeProperty();
}
}
}
}
}