So, because it runs at 20-30 fps on an android phone, it must be a inherently slow design?
Short answer: No, but it's a strong indication. 300 active entities is ridiculously small set.
1) Expanded memory requirements (vastly if components are fine grain)
2) Increased pointer traversal
3) Dictionary lookup per component
4) No control over memory layout = no access pattern can be cache oblivious
= explosion of cache misses, in addition to extra code complexity.
Entity e = entitySystem.get(globalId);
e.getAs(Position.class).x = 5;
e.getAs(Damage.class).hitpoints = 145;
e.getAs(Renderable.class).foregroundColour = Color.red;
7 dictionary look-ups and something like 7 cache misses (on average) if this is in a tight loop...I'm too lazy to figure the upper bound.
Notice he said the Java implementation on Android has serious performance problems. The standard Java implementation would have no problem with this.
Relatively, I'd expect to the impact to be larger on JIT Java-a-likes. Interp will tend to hide the cost of cache misses.