Распределение бесплатной игры - PullRequest
5 голосов
/ 07 декабря 2010

Мой код в основном свободен для выделения, однако GC запускается каждые 30 секунд или около того, когда скорость составляет 60 кадров в секунду.Проверка приложения с DDMS на выделение показывает, что выделено ALOT SimpleListIterator.Есть также некоторые вещи, которые выделяются, потому что я использую Exchanger.

SimpleListIterator поставляется для каждого цикла for (T obj : objs) {}.У меня сложилось впечатление, что компилятор / переводчик оптимизировал бы их, чтобы они не использовали итераторы для типов, которые его поддерживают (я в основном использую только ArrayList), но, похоже, это не так.

Как можно избежать выделения всехэти SimpleListIterators?Одним из решений было бы переключение на обычные циклы for for (int i = 0; i < size; ++i) {}, но мне нравится для каждого цикла: (

Другим способом было бы расширение ArrayList, который возвращает Iterator, который выделяется только один раз.

Третий способ, который я взломал вместе, - это использование статической вспомогательной функции, которая возвращает Collection, который повторно использует Iterator. Я взломал что-то подобное вместе, но кастинг выглядит очень хакерским и небезопасным.Я использую ThreadLocal? См. Ниже:

public class FastIterator {
    private static ThreadLocal<Holder> holders = new ThreadLocal<Holder>();

    public static <T> Iterable<T> get(ArrayList<T> list) {
        Holder cont = holders.get();

        if (cont == null) {
            cont = new Holder();

            cont.collection = new DummyCollection<T>();
            cont.it = new Iterator<T>();

            holders.set(cont);
        }

        Iterator<T> it = (Iterator<T>) cont.it;
        DummyCollection<T> collection = (DummyCollection<T>) cont.collection;

        it.setList(list);
        collection.setIterator(it);

        return collection;
    }

    private FastIterator() {}

    private static class Holder {
        public DummyCollection<?> collection;
        public Iterator<?> it;
    }

    private static class DummyCollection<T> implements Iterable {
        private Iterator<?> it;

        @Override
        public java.util.Iterator<T> iterator() {
            return (java.util.Iterator<T>) it;
        }

        public void setIterator(Iterator<?> it) {
            this.it = it;
        }
    }

    private static class Iterator<T> implements java.util.Iterator<T> {
        private ArrayList<T> list;
        private int size;
        private int i;

        @Override
        public boolean hasNext() {
            return i < size;
        }

        @Override
        public T next() {
            return list.get(i++);
        }

        @Override
        public void remove() {

        }

        public void setList(ArrayList<T> list) {
            this.list = list;
            size = list.size();
            i = 0;
        }

        private Iterator() {}
    }
}

Ответы [ 3 ]

4 голосов
/ 07 декабря 2010

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

2 голосов
/ 07 декабря 2010

Вероятно, наилучшим подходом будет использование дизайна Decorator. Создайте класс, который принимает коллекцию в конструкторе и реализует интерфейс Iterable, вызывая обернутый класс и повторно используя возвращаемый итератор.

0 голосов
/ 07 декабря 2010

Два дополнительных подхода для избежания выделения итераторов.Во-первых, нужно использовать идиому обратного вызова:

public interface Handler<T> {
  void handle(T element);
}

public interface Handleable<T> {
  void handleAll(Handler<T> handler);
}

public class HandleableList<T> extends ArrayList<T> implements Handleable<T> {
  public void handleAll(Handler<T> handler) {
    for (int i = 0; i < size(); ++i) {
      handler.handle(get(i));
    }
  }
}

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

Второй подход заключается в использовании идиомы курсора:

public interface Cursor<T> {
  void reset();
  boolean next();
  T current();
}

public class CursoredList<T> extends ArrayList<T> implements Cursor<T> {
  private int _index = -1;

  public void reset() {
    _index = -1;
  }

  public boolean next() {
    return ++_index >= size();
  }

  public T current() {
    return get(_index);
  }
}

Конечно, это то же самое, что реализация Iterable и Iterator для вашего подтипа ArrayList, но это ясно показывает курсорместоположение как состояние на самой коллекции.

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