My code is basically allocation free, however the GC runs every 30 seconds or so when at 60fps. Checking the app with DDMS for allocation shows there is ALOT of SimpleListIterator
being allocated. There is also some stuff being allocated because i use Exchanger
.
The SimpleListIterator comes from for each loops for (T obj : objs) {}
. I was under the impression that the compilator/translator would optimize those to not use iterators for types that support it (I basically only use ArrayList) but that seems to not be the case.
How can I avoid allocating all these SimpleListIterators
? One solution would be to switch to regular for loops for (int i = 0; i < size; ++i) {}
but I like for each loops :(
Another way would be to extend ArrayList which returns an Iterator
that is only allocated once.
A third way I hacked together is using a static helper function which returns a Collection
which is reusing an Iterator
. I hacked something like this together but the casting feels very hackish and unsafe. It should be thread safe though as I use ThreadLocal
? See below:
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() {}
}
}
Open your Task Manager and go to the Details tab across the top of the application. You'll see a ton of services and programs running and you need to right-click the specific game you want to allocate more RAM to, then hover over “Set priority”.
Size of physical RAM: Games often use between ¼ and ½ of the physical RAM amount on the device.
Advantages of Dynamic Memory allocationThis allocation method has no memory wastage. The memory allocation is done at run time. Memory size can be changed based on the requirements of the dynamic memory allocation. If memory is not required, it can be freed.
You should not use for each in Android games. I think this official video talks about that too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With