我们的服务器最近一直在下降很多,我的任务是改善被确定为罪魁祸首的一组类的内存使用情况。
我有一个初始化对象实例的代码,如下所示:
布尔var1; 布尔var2; 。 。 。 boolean var100;
void setup() {
var1 = map.hasFlag("var1");
var2 = map.hasFlag("var2);
.
.
.
if (map.hasFlag("some flag") {
doSomething();
}
if (var1) {
increment something
}
if (var2) {
increment something
}
}
设置代码大约需要1300行。我的问题是,在使用太多实例变量方面,这种方法是否有可能更有效。
顺便说一下,实例变量用在“main”方法handleRow()中,例如:
handleRow(){
if (var1) {
doSomething();
}
.
.
.
if (var100) {
doSomething();
}
}
我想的一个解决方案是通过删除setup方法中的实例变量并在需要时直接从地图中调用它来更改实现:
handleRow(){
if (map.hasFlag("var1") {
doSomething();
}
.
.
.
if (map.hasFlag("var100") {
doSomething();
}
}
这是我正在考虑的一个解决方案,但我想听听社区的意见。 :)
答案 0 :(得分:7)
如果这些都是boolean
个变量,请考虑使用BitSet
。您可能会发现,根据填充,内存占用量减少了8倍甚至32倍。
答案 1 :(得分:1)
您可以通过将值存储在位集中来节省内存(但如果您的内存使用是一个真正的问题,那么它可能是时间上的净增益)。
如果类是不可变的(一旦你创建它,你永远不会改变它),那么你可以通过在Flyweight模式上使用变体来获得。在这里,您可以在弱hashmap中存储正在使用的对象,并在工厂中创建对象。如果创建的对象与现有对象相同,则工厂将返回此前一个对象。根据有多少重复的物体,记忆中的节省可以忽略不计。
如果类不是不可变的,但是有这样的重复,你仍然可以使用Flyweight模式,但你必须做一种写时复制,其中改变一个对象使它从使用共享内部改变表示自己的一个(或来自flyweight商店的新表示)。这在时间上更复杂但更昂贵,但如果合适的话,节省的费用也会很高。
答案 2 :(得分:1)
您可以使用命令模式:
public enum Command {
SAMPLE_FLAG1("FLAG1") {
public abstract void call( ){
//Do you increment here
}
},
SAMPLE_FLAG2("FLAG2") {
public abstract void call( ){
//Do you increment here
}
};
private Map<String, Command> commands = new HashMap<String, Command>( );
static {
for ( Command cmd : Command.values( )) {
commands.put( cmd.name, cmd);
}
};
private String name;
private Command( String name) {
this.name = name;
}
public Command fromString( String cmd) {
return commands.get( cmd);
}
public abstract void call( );
}
然后:
for( String $ : flagMap.keySet( )) {
Command.fromString( $).call( );
}
答案 3 :(得分:1)
当每个带有开销的布尔值占用16个字节时,100 boolean
个变量将占用1.6k的内存(这有点不太可能)我认为这不会成为问题的根源。
通过调用地图取代这些标志会对性能产生负面影响,因此您的更改可能会使事情变得更糟。
在重新设计代码之前(命令模式看起来很合适),您应该进一步了解要求您解决的内存泄漏问题。
查找类不断添加的映射,静态变量集合等。一旦找到了内存增长的原因所在,就可以决定重构哪个类的部分。