Impact of 'instanceof' in Android Java code - android

Does the instanceof keyword bear with it a relatively heavier impact on the Android platform (and more speciffically the mobile phones running the Dalvik VM?

I do not think instanceof bears a heavier impact on the Dalvik VM opposed to the JVM.
If you have any doubts, you can see for yourself when you run your application with a tool called Allocation Tracker that comes standard as a tool for the DDMS.

I found that instanceof is mostly faster (around 60-85% of the time). However this percentage falls when the phone is presented with background activity (e.g. GC, touching, buttons, shaking it etc.) but instanceof remains faster above 50% of the time. When the number of cycles is made very large (i.e. > 1000000) instanceof is nearly always faster.
The order in which the two while loops are presented (i.e. first the instanceof loop and then the field check loop) affects the results but instanceof remains the fastest.
AbstractParticle circleParticle = new CircleParticle();
int cycles = 100000
long now1 = System.currentTimeMillis();
int i = 0;
while(i<cycles) {
if(circleParticle instanceof CircleParticle) {
i++;
}
}
long timetaken1 = (System.currentTimeMillis()-now1);
long now2 = System.currentTimeMillis();
int j = 0;
while(j<cycles) {
if(circleParticle.type == AbstractParticle.TYPE_CIRCLE) {
j++;
}
}
long timetaken2 = (System.currentTimeMillis()-now2);
if(timetaken1 < timetaken2) {
type1won++;
}
else if(timetaken2 < timetaken1){
type2won++;
}
Log.d("instanceof test","type 1 favoured : "+((float)type1won/(type1won+type2won)));

Related

Android Random Number Generator Hangs

I'm writing a very simple program. What I want is a 50/50 chance and display option A or option B.
Here is my code:
int min = 0;
int max = 100;
int randomValue;
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
btn_50_50.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (randomValue < 50) {
// do something
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
} else if (randomValue > 50) {
// do something else
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
});
It works but if i press the button many times, especially if I kind of spam it, it stops working and only displays the last generated option.
I checked with a Toast message and it seems that it stops generating new numbers. It happens both in emulator and on a real device.
I have also tried importing java.util.Random and using that but exactly the same results.
Is there any better way to do this or a way to force the RNG to restart?
What happens when randomValue is exactly 50? :)
It's a 1 in 100 chance but it's bound to happen at some point.
Also, a 50/50 chance is the same as having 2 options and the chance of it being one of the options.
For example rolling (0,1) and checking if it's 0:
boolean isRandomChance = random.nextInt(0, 2) == 0;
Or, just the built in random boolean generator (true/false):
boolean isRandomChance = random.nextBoolean();

Is my target selection AI efficient?

quick question. I am developing a top-down 2d Platformer game with lots of enemies in the map (at least a hundred spawn at the start of each level). Each enemy uses an AI that searches the map for objects with a specified tag, sorts each object into a list based on their distance, then reacts to the object closest to them.
My code works, but the thing is, if the machine my game is running on is slow, then my game lags. I want to be able to port my game to Android and iOS with low end specs.
In pursuit of putting less strain on the CPU, is there a better way to write my AI?
Here is my code:
void Start () {
FoodTargets = new List<Transform>(); // my list
SelectedTarget = null; // the target the enemy reacts to
myTransform = transform;
AddAllFood ();
}
public void AddAllFood()
{
GameObject[] Foods = GameObject.FindGameObjectsWithTag("Object");
foreach (GameObject enemy in Foods)
AddTarget (enemy.transform);
}
public void AddTarget(Transform enemy)
{
if (enemy.GetComponent<ClassRatingScript>().classrating != 1) { // classrating is an attribute each enemy has that determines their identity (like if they are a plant, a herbivore or a carnivore)
FoodTargets.Add (enemy); // adds the object to the list
}
}
private void SortTargetsByDistance() // this is how I sort according to distance, is this the fastest and most efficient way to do this?
{
FoodTargets.Sort (delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
private void TargetEnemy() // this is called every 4 frames
{
if (SelectedTarget == null) {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
else {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
}
if (optimizer <= 2) { // this is a variable that increments every frame and resets to 0 on the 3rd frame. Only every 3rd frame is the target enemy method is called.
optimizer++;
} else {
TargetEnemy ();
// the rest are attributes that the AI considers when reacting to their target
targetmass = SelectedTarget.GetComponent<MassScript> ().mass;
targetclass = SelectedTarget.GetComponent<ClassRatingScript> ().classrating;
mass = this.GetComponent<MassScript> ().mass;
classrating = this.GetComponent<ClassRatingScript> ().classrating;
distance = Vector3.Distance (transform.position, SelectedTarget.transform.position);
optimizer = 0;
}
Is there a more optimized way of doing this? Your help will be much appreciated. Thanks in advance!
I'm not awfully familiar with C# or Unity but I would look very carefully at what sorting algorithm your sorting method is using. If all you want is the closest Game Object, then sorting isn't necessary.
The fastest sorting algorithms, such as Quicksort, are O(n*log(n)). That is to say that the time it takes to sort a collection of n objects is bounded by some constant multiple of n*log(n). If you just want the k closest objects, where k << n, then you can perform k iterations of the Bubble Sort algorithm. This will have time-complexity O(k*n), which is much better then before.
However, if you only need the single closest object, then just find the closest object without sorting (pseudocode):
float smallestDistance = Inf;
object closestObject = null;
foreach object in objectsWithTag {
float d = distance(object, enemy);
if (d < smallestDistance) {
smallestDistance = d;
closestObject = object;
}
}
This extremely simple algorithm has time complexity O(n).

Large static float and double arrays causing App to slow down

This is more of a generic question which has to do with static variables and the process life cycle.
I have developed a heavy multi threaded signal processing Android app. It is targeted at API level 9 and above, and if I can it will restricted to only dual core devices. This is purely an academic App and not intended for the general user, and has been developed for teaching Digital Signal Processing. So for this reason I am calculating the DFT many times and so forth so there is quite a bit of computation and size allocation required.
I have declared a bunch of static float and double arrays which get used in static functions like in the example below. The complete code is is a bit to big to put here, so the example below just illustrates the idea.
public class SpecMod {
//Example of global static declarations
static double [][] spectrum = null;
static double [][] phaseMat = null;
static float [][] mframes = null;
static float [][] sframes = null;
static double [] mag = null;
static double [] Pxx = null;
static double [] GAMk = null;
static int nfft = 512;
static float nsegs = 560;
//Compute FFT data
public static void calcSpec(int fs, float [] buffer, float f, float g){
//Example of static array memory allocation
sframes = new float[nlen][(int) nsegs];
spectrum = new double[nfft][(int) nsegs];
phaseMat = new double[nfft][(int) nsegs];
mframes = new float[nlen][(int) nsegs];
mag = new double[nfft];
Pxx = new double[nfft];
GAMk = new double[nfft];
}
public static void fillArrays(){
//Example of array manipulation
for (int j = 0; j < nsegs; j++) {
for (int i = 0; i < nfft; i++) {
mag[i] = spectrum[i][j];
phase[i] = phaseMat[i][j];
Pxx[i] = Math.pow(Math.abs(mag[i]), 2);
GAMk[i] = (Pxx[i] / muPnn[i]);
}
}
}
}
The application is working great as it is. The problem lies in different execution times when say the function fillArrays() gets called. The first time the function is called it takes only 4 seconds to complete, however the second and each subsequent time it is run it takes closer to 30 seconds to complete. In log cat you can see that the heap size does increase drastically the second time, but every subsequent time it stays about the same. In MAT the two dimensional array 'spectrum' retains a large portion of heap. This is understandable as it would contain nfft*nsegs (512*560) sized data stored as doubles.
So I am not sure if the time taken is due to the Garbage collector or perhaps the interpreter going into each step of the for loops (strange tho if the first execution is still short). I thought maybe for all other arrays, setting them to non-static weakreferences so the garbage collector can clean them up, but it seems everything I try is to the same time effects.
So the question is, when using large array objects what is the most effective way to allocate space for them. At the moment they are static, but are not final as the size changes frequently due to user preference. Any help would be great thanks.
Note this is just example code, calcSpec() gets called each time the user changes parameters or a new audio file is loaded to compute frequency data 'spectrum', then only after calcSpec is called, the user can call fillArrays(). In terms of profiling, I have been using MemoryAnalyzer and allocation tracker. The odd thing here the time increase is only in fillArrays(). The first execution it take 4seconds, the second (without calling calcSpec() again, so the same spectrum data is used again) it takes 30 seconds. In both Mat and allocation tracker the Retained size and allocation size are the same for every execution.

Determining even/odd numbers (integers)?

I feel stupid asking such a simple question, but is there an easy way to determine whether an Integer is even or odd?
if ((n % 2) == 0) {
// number is even
}
else {
// number is odd
}
It's not android specific, but a standard function would be:
boolean isOdd( int val ) { return (val & 0x01) != 0; }
Many compilers convert modulo (%) operations to their bitwise counterpart automatically, but this method is also compatible with older compilers.
You can use modular division (technically in Java it acts as a strict remainder operator; the link has more discussion):
if ( ( n % 2 ) == 0 ) {
//Is even
} else {
//Is odd
}
If you do a bitwise-and with 1, you can detect whether the least significant bit is 1. If it is, the number is odd, otherwise even.
In C-ish languages, bool odd = mynum & 1;
This is faster (performance-wise) than mod, if that's a concern.
When somehow % as an operator doesn't exist, you can use the AND operator:
oddness = (n & 1) ? 'odd' : 'even'
Similar to others, but here's how I did it.
boolean isEven = i %2 ==0;

Are dimen values cached?

Is there any performance gain over doing the following:
final int pixels = getResources.getDimensionPixelSize(R.dimen.pixels);
for (CustomView view: views) {
view.setPixelValue(pixels);
}
vs.
for (CustomView view: views) {
view.setPixelValue(getResources.getDimensionPixelSize(R.dimen.pixels));
}
Or are dimens values cached / the bytecode optimised / some other optimisation that makes this redundant?
Looking at Resources.getDimentionPixelSize() and deeper till AssetManager.loadResourceValue() which is native it's impossible to say. However, from Resources.getDimentionPixelSize() source it's possible to say the following:
public int getDimensionPixelSize(int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
mTmpValue = value = new TypedValue();
}
getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimensionPixelSize(
value.data, mMetrics);
}
throw new NotFoundException(
"Resource ID #0x" + Integer.toHexString(id) + " type #0x"
+ Integer.toHexString(value.type) + " is not valid");
}
}
It will lock resources by synchronized (mAccessLock) (read, if some other thread of you will try to access resources same moment - on of them will wait);
It will call some float math inside TypedValue.complexToDimensionPixelSize();
It will probably create TypedValue object;
It will do at least 5 method calls;
So, maybe it's cached somewhere in native, but even so, call will be definitely not free for you.
Here's some measurements I've done for this question (with only single thread accessing resources):
int pixels = 0;
Resources res = getResources();
long ms = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
pixels = res.getDimensionPixelSize(R.dimen.my_dimen);
}
Log.e(TAG, "Time " + (System.currentTimeMillis() - ms));
On S6 with Android Lollipop it gives about 816 ms, or 8160 nano-sec / call.
Finally, in your case (I believe you have maximum 10-20 iterations) it really doesn't matter in terms of performance. In more iterations and / or some concurrency in access to resources in might be significant.
Personally I would suggest to do it outside for better style and small but still speed improvement.

Categories

Resources