Как я могу десериализовать очень большой класс на Android? - PullRequest
2 голосов
/ 25 марта 2011

Я работаю над переносом приключенческой игры в подземелье Roguelike на Android. http://tyrant.sourceforge.net

Когда я запускаю свою программу, я сначала инициализирую мир и все его объекты. У меня есть класс, который содержит 3 миллиона (!) Записей HashMap. Когда я пытаюсь инициализировать этот класс, на моем Android требуется более 5 минут, что является очень недопустимым отрезком времени. Как только класс инициализирован, игра работает отлично и довольно весело.

Поэтому я подумал, что могу сериализовать этот объект и перезагрузить его во время выполнения. Я сериализую его и упаковываю в файл .APK, его размер превышает 5 МБ. Android просто задыхается и выдает ошибку OutOfMemory.

Я могу десериализовать часть класса (800 КБ), а затем динамически создать остальные записи. Это все еще занимает довольно много минут, чтобы закончить, все еще нужно создать 3 миллиона записей из сериализованных данных. Но я знаю, что мой код сериализации работает нормально.

Как я могу сохранить этот очень большой файл класса на Android и загрузить его позже? Какие варианты я могу изучить? Заставить моего пользователя подождать 5 минут, пока приложение запустится, не очень хорошо.

Вот класс беспокойства в исходном коде: http://tyrant.cvs.sourceforge.net/viewvc/tyrant/tyrant/mikera/engine/Lib.java?view=markup

и тревожное поле:

private transient Map types;

(я знаю, что это переходный процесс)

в конечном итоге хранится более 3 миллионов записей!

Ответы [ 3 ]

0 голосов
/ 25 марта 2011

Ну, отчасти проблема в том, что находится на карте types.

Из того, что я могу разглядеть, это фактически Map<String, Map<Integer, List>>, где карты 2-го уровня действительно не разреженные массивы. Если бы вы выбрали лучшую структуру данных, она бы занимала меньше места, и вы могли бы построить ее намного быстрее. (Я думаю, что вы правы, что не сериализовали его ... так как, похоже, его нельзя изменить во время игры.)

A HashMap<Integer, Object> занимает намного больше места, чем Object[].


Лучшая структура данных была бы Map<String, LevelMap>, где LevelMap примерно такой:

public class LevelMap {
    private static final ArrayList<String> EMPTY = Collections.emptyList();

    private ArrayList<String>[] levels;
    private int firstLevel;

    public LevelMap(int firstLevel, int lastLevel) {
        this.firstLevel = firstLevel;
        levels = new ArrayList<String>[lastLevel - firstLevel + 1];
    }

    public static void addToTypeMap(String key, String value, 
            int firstLevel, int lastLevel) {
        LevelMap l = types.get(key);
        if (l == null) {
            l = new LevelMap(firstLevel, lastLevel);
            types.put(key, l);
        } 
        l.add(value, firstLevel, lastLevel);
    }

    public void add(String value, int firstLevel, int lastLevel) {
        ensure(firstLevel, lastLevel);
        for (int i = firstLevel; i <= lastLevel; i++) {
            j = i - this.firstLevel;
            if (levels[j] == null) {
                levels[j] == new ArrayList<String>();
            }
            levels[j].add(value);
        }
    }

    private void ensure(int firstLevel, int lastLevel) {
        // Make sure that these levels are in the levelmap
        // If necessary, reallocate this.levels and adjust this.firstLevel
    }

    public String get(int level) {
        if (level < this.firstLevel ||
            level >= this.firstLevel + levels.length ||
            levels[level - this.firstLevel] == null) {
            return EMPTY;
        } else {
            return levels[level - this.firstLevel];
        }
    }
}
0 голосов
/ 25 марта 2011
  1. Вы пишете игру и пытаетесь сериализовать огромный объект, не можете ли вы разбить его на уровни или что-то в этом роде и избегать все время удерживать.
  2. Вы смотрели на Проектирование для повышения производительности на сайте разработчика Android?
  3. Узнайте, как использовать инструменты повышения производительности на Android Профилирование с Traceview .
0 голосов
/ 25 марта 2011

Я думаю, что частью вашей проблемы является то, что ваши записи слишком толстые. Просматривая свой код, вы сохраняете HashMap свойств со строковыми ключами для каждой вещи? Это, вероятно, убивает тебя прямо там. Первое, что нужно сделать, это переключиться на основанную на перечислении HashMap и посмотреть, влияет ли это на производительность [и сумма применяется ко всем вашим строкам повсюду - замените их на перечисления везде, и используйте утилиту, которая преобразует их в строки, если они должен отображаться пользователям]

Теперь, почему именно у вас есть 3 миллиона записей?!?! это весь твой мир? Если да, можете ли вы разбить его на шахматную доску в 100 квадратов, записать в 100 различных файлов и начать загружать только те квадраты, в которых находятся ваши герои, а потом загружать остальные в фоновом режиме?

...