Экономия на переменных экземпляра - PullRequest
0 голосов
/ 17 августа 2010

Наш сервер в последнее время сильно ломался, и мне было поручено улучшить использование памяти набором классов, которые были признаны виновными.

У меня есть код, который инициализирует экземпляр объекта и выглядит так:

boolean 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 строк.Мой вопрос заключается в том, возможно ли, чтобы этот метод был более эффективным с точки зрения использования слишком большого количества переменных экземпляра.

Переменные экземпляра, кстати, используются в "основном" методе handleRow (), где, например:

handleRow(){
   if (var1) {
     doSomething();
   }
   .
   .
   . 
   if (var100) {
     doSomething();
    }
}

Я думаю, что одним из решений является изменение реализации путем удаления экземпляра.Переменные в методе установки и просто вызов его напрямую с карты, когда мне это нужно:

handleRow(){
  if (map.hasFlag("var1") {
      doSomething();
  }
  .
  .
  . 
  if (map.hasFlag("var100") {
     doSomething();
  }
}

Это одно решение, которое я рассматриваю, но я хотел бы услышать мнение сообщества.:)

Ответы [ 4 ]

7 голосов
/ 17 августа 2010

Если это действительно все boolean переменные, рассмотрите вариант использования BitSet.Вы можете обнаружить, что это уменьшает объем памяти в 8 или даже 32 раза в зависимости от заполнения.

1 голос
/ 17 августа 2010

100 boolean переменные будут занимать 1,6 КБ памяти, когда каждый логический тип с дополнительными данными занимает 16 байтов (что немного много), я не думаю, что это будет источником проблемы.

Заменаэти флаги с вызовами в карту будут негативно влиять на производительность, поэтому ваши изменения, вероятно, ухудшат ситуацию.

Перед тем, как приступить к переработке своего кода (шаблон команды выглядит хорошим кандидатом), вам следует изучить, гдеутечка памяти - это то, что вас просят устранить.

Ищите карты, к которым классы продолжают добавлять, коллекции, являющиеся статическими переменными и т. д. Как только вы выясните, в чем причина роста памяти, вы можете решить, какую частьваших классов для рефакторинга.

1 голос
/ 17 августа 2010

Вы можете использовать шаблон команды:

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( ); 
}
1 голос
/ 17 августа 2010

Вы можете сэкономить память ценой времени (но если использование памяти является реальной проблемой, то это, вероятно, выигрыш во времени), сохраняя значения в битовом наборе.

Если класснеизменяемый (когда вы его создаете, вы никогда не меняете его), то, возможно, вы можете получить выгоду, используя вариант на шаблоне Flyweight.Здесь у вас есть хранилище используемых объектов в слабой хэш-карте, и вы создаете свои объекты на фабрике.Если вы создаете объект, идентичный существующему объекту, ваша фабрика возвращает этот предыдущий объект.Сохранение в памяти может быть незначительным или значительным в зависимости от количества повторяющихся объектов.

Если класс не является неизменным, но есть такое повторение, вы все равно можете использовать шаблон Flyweight, но вам придетсявыполнить своего рода копирование при записи, когда изменение объекта приводит к его изменению с использования общего внутреннего представления на его собственное (или новое из хранилища flyweight).Это еще сложнее и все же дороже с точки зрения времени, но опять же, если это целесообразно, экономия может быть значительной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...