Are dimen values cached? - android

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.

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();

Sorting of List<Object>

I need to sort the products by High to Low & Low to High of its Price.I have done Low to High by using following code.But dont know how to implement High To Low?
Your answer is more appreciated...
public static Comparator<Restaurant_Beam> strPriceFilterL2H = new Comparator<Restaurant_Beam>() {
#Override
public int compare(Restaurant_Beam lhs, Restaurant_Beam rhs) {
int CompareResult = 0;
if (Config.L2HFilterClicked == "L2H") {
CompareResult = (int) Math.round(Double.parseDouble(lhs.getIG_SALES_PRICE()) - Double.parseDouble(rhs.getIG_SALES_PRICE()));
}
//Used else if for H2L.But did not get it as perfect
else if (Config.L2HFilterClicked == "H2L") {
CompareResult = (int) Math.round(Double.parseDouble(lhs.getIG_SALES_PRICE()) + Double.parseDouble(rhs.getIG_SALES_PRICE()));
}
return CompareResult;
}
};
Change the second compare expression to this one:
CompareResult = (int) Math.round(Double.parseDouble(Double.parseDouble(rhs.getIG_SALES_PRICE()) - Double.parseDouble(lhs.getIG_SALES_PRICE()));
Also I'd like to point out a few things
consider doing Double comparison with epsilon
it's a good practice to check objects before comparing them
parsing each time you compare is really bad design. It would be better if you parse values somewhere in advance, consider changing your type. Currently it's not efficient.

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).

Android: Converting a set of functions into an equation

I am 99% sure that this cannot be done, however I thought I would ask to be certain.
I am attempting to create an application that calculates the required dice roll for an action in a popular tabletop war game.
The following is this calculation in Java
int x = ((WSattacker * 2) - WSdefender);
int y = (WSattacker - WSdefender);
String result;
// Calculation for a +5
if (x <= -1) {
result = "5+";
}
// Calculation for a +4
else if (x >= 0 && y <= 0) {
result = "4+";
}
// Calculation for a +3
else if (y > 0) {
result = "3+";
} else {
result = "Error";
}
return result;
Now my issue is that to avoid copywriter infringement I cannot mention the name of the game in my application, and probably cannot hard code the above calculation in the app.
This means that it is difficult to tell a potential user what the app will do.
The only solution I can think of is to make the application generic and allow the user to input the calculation required in the form of an equation.
An equation that I can place anonymously on a public board or similar.
Therefore my questions are as follows.
Is there another way of going about this?
If no, is it possible to condense the above code into a single expression/ equationi.e. one that removes the if and else statements
To answer question 2:
result = test_condition_1 ? result2_if_true : (test_condition_2 ? result2_if_true : test3_or_result2);
You can then build up 'compound' test conditions this way, and it's based upon ternary operators.
EDIT
Ternary operators are a short-hand way of writing if..then..else statments, and more information can be found in the wiki-link above. An example of its use is below, which you can compile and run:
public class TernaryTest {
public static void main(String [] args){
int x = 14;
int y = 5;
String result = ( x <= 10 ) ? "Less than 10" : "More than 10";
System.out.println("Result is: " + result);
}
}
Try running it and see the result as you change the value of x to understand how it works. Then it's possible to extend it to include and else by replacing the "more than 10" string.

Impact of 'instanceof' in Android Java code

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)));

Categories

Resources