Snake self-eating optimization - java

I write my own Snake-game, where Snake is ArrayList of Points and I use this method to check self-eating:
public void checkSelfEating() {
for (int i = 1; i < body.size(); i++) {
if (body.get(i).equals(body.get(0))) {
sgv.setGameOverState(true);
sgv.setMessage("Game over!");
System.out.println("SelfEatingdetected");
}
}
}
Video (Started at 35 s.)
But it is too slow, and snake do about 5 moves until game is over. Is there a better solution?

Store the body units in a HashSet via add and remove calls. O(1). Furthermore if you use a LinkedHashSet it will be very easy to manage the head and tail (per comment).
This all being said, while this is the correct data structure and answers your question, I have absolutely no idea why having to do a for loop over a few dozen elements or so is making your program so horribly slow. I strongly recommend profiling and finding the actual bottleneck as I'm not even sure a hash set will be faster at this scale.

Related

How do I efficiently iterate through a big list?

I want to make a open world 2D Minecraft like game and have the world load in Chunks (just like MC) with a size of 16x16 blocks (a total of 256 blocks). But I found out through iterating 256 times that it takes almost 20ms to iterate completely with a code like this:
long time = System.nanoTime();
for(int i = 0; i < 16*16; i++)
{
System.out.println(i);
}
System.out.println(System.nanoTime() - time);
And since I'm not only going to print numbers but also get a block, get it's texture and draw that texture onto the frame, I fear it might take even longer to iterate. Maybe I just exaggerate a bit, but is there a way to iterate faster?
It's not the iteration that takes 20ms, it's println();.
The following will be much faster:
long time = System.nanoTime();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 16*16; i++)
{
sb.append(i + System.getProperty("line.separator"));
}
System.out.println(sb);
System.out.println(System.nanoTime() - time);
So, first off, take into account that a list with 256 is not considered generally to have a big size.
The main thing consuming time your code is not iterating through the list but using System.out.println(). Printing to console (or any I/O action) tends to take longer than other instructions.
When I try your code locally I get roughly 6 ms but if I do something like this:
long secondStart = System.nanoTime();
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0; i < 16*16; i++)
{
stringBuffer.append(i);
stringBuffer.append("\n");
}
System.out.println(stringBuffer);
System.out.println(System.nanoTime() - secondStart);
I get 0.5ms.
If that approach is not suitable for your needs then you would need to do as other comments say, consider traversing different parts of the list in parallel, maybe move to a different kind of traversal or even a different kind of structure.
Hope this helps.
You should ask yourself if you really need to do all that work. Do you need to draw things that are not seen by the camera for example? Of course not, so exclude every block in that chunk that is outside the camera rect.
Filtering out the blocks not seen implies some overhead but it is generally worth it compared to drawing every block in the chunk on each render update because drawing stuff is quite a heavy operation.
If you only want to speed up the traversal you could spawn threads that traverse the chunk in parallell or buy better hardware. But it is better to start with the question of how you could achieve the same result with less work put in.
On the other hand your computer should probably be able to draw 256 textures without problem especially if done on the gpu. So maybe do some testing before making premature optimizations.
PS. It isn't really the traversal itself you want to optimize for but rather the work done in each iteration. Just iterating 256 times is going to be quite fast.

execution of task in java within specified time

I want to execute few lines of code with 5ms in Java. Below is the snippet of my code:
public void delay(ArrayList<Double> delay_array, int counter_main) {
long start=System.currentTimeMillis();
ArrayList<Double> delay5msecs=new ArrayList<Double>();
int index1=0, i1=0;
while(System.currentTimeMillis() - start <= 5)
{
delay5msecs.add(i1,null);
//System.out.println("time");
i1++;
}
for(int i=0;i<counter_main-1;i++) {
if(delay5msecs.get(i)!=null) {
double x1=delay_array.get(i-index1);
delay5msecs.add(i,x1);
//System.out.println(i);
} else {
index1++;
System.out.println("index is :"+index1);
}
}
}
Now the problem is that the entire array is getting filled with null values and I am getting some exceptions related to index as well. Basically, I want to fill my array list with 0 till 5ms and post that fill the data from another array list in it. I've not done coding since a long time. Appreciate your help.
Thank You.
System.currentTimeMillis() will probably not have the resolution you need for 5ms. The granularity on Windows may not be better than 15ms anyway, so your code will be very platform sensitive, and may actually not do what you want.
The resolution you need might be doable with System.nanoTime() but, again, there are platform limitations you might have to research. I recall that you can't just scale the value you get and have it work everywhere.
If you can guarantee no other threads running this code, then I suppose a naive loop and fill will work, without having to implement a worker thread that waits for the filler thread to finish.
You should try to use the Collection utilities and for-each loops instead of doing all this index math in the second part.
I suppose I should also warn you that nothing in a regular JVM is guaranteed to be real-time. So if you need a hard, dependable, reproducible 5ms you might be out of luck.

What is faster and best for with if and return or while?

I have a question about the for and while loops, as we have to travel a value until a condition is met. I wonder which is more efficient at low level, and why?
That is, these two codes give the same result:
FOR:
for (int i = 0; i<10 ; i++)
{
if (i==4)
{
return;
}
}
WHILE:
int i=0;
while (i<10 and i!=4)
{
i++;
}
This is a small example of a possible loop, and we could be looking at a record of thousands.
What code is more effective? I've always said that I have to use a while in this case, but I wonder if a low level is still better while or better yet is for.
Thank you very much.
The answer is: it doesn't matter.
You will not see any difference in performance in either, unless you really try hard to make code to see the difference, and what really matters is the readability of your code (and this is where you'll save time and and money in the future), so use whichever one is more understandable.
In your case, i'll suggest the While approach ...
I'll also suggest reading this article by Eric Lippert: How Bad Is Good Enough?, just in case you're not sold on the readability vs. silly optimizations :)
They should compile very similarly. At a low level you are looking at executing the commands within the loop, and then you will have two calls to compare a value and jump to the next block of code if the condition calls for exiting the loop.
As mentioned above, while should lead to better readability and thus is the better choice.
Both for and while are the same.
The only difference is where you place the condition.
internally the while loop uses the 'for' syntax in low level.
In your scenario. While is the best option ** if you don't know the upper limit **
you can use
While(i!=4)
{
i++
}
Use for loop if you know the upper limit, else while is the best friend.

i++ or i-- in a for loop? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
While writing a for loop where both start and end conditions are known, which way is better? Let's say I have to iterate a loop for addition of an array elements of size 5. In this case which one of the following would be more efficient as far as execution time is concerned? Which one will give better performance?
for (i = 0; i < 5; i++)
{
/* logic */
}
OR
for (i = 4; i >= 0; i--)
{
/* logic */
}
Apart from the difficulty in writing i = 5 - 1; that is i = 4;, are there any other considerations?
It's usually recommended to concentrate on making code as clear and as logical as possible, without worrying about micro-optimizations or other factors. In your case, the first one is the better choice, since most programmers are more used to traverse an array in that order.
Both versions will have the same result (given that they're implemented correctly) and will have exactly the same run time.
EDIT: #Zane mentioned in a comment that looping backwards to zero was faster some time ago. It was, the reason for it was that comparing a variable to zero was faster. Given that computers were much much slower those days, such optimizations were encouraged. Those days are indeed over...
There is something wrong in your code.
The first loop is fine but the second while never execute:
it runs for 0 times. It should be
for(i=4;i>=0;i--){}
Besides, if you ask which is better, its your choice, with which one you are comfortable with.
For me, I feel the first one to be more comfortable.
In most cases it wouldn't matter, however there are some situations where non-obvious side-effects might interfere.
Consider a loop:
for(int i = 0; i < strlen(str); i++) {/* do stuff on i-th elem */}.
Here on each iteration the strlen(str) will be reevaluated (unless optimized by compiler) even though it's completely unnecessary; the programmer most likely didn't even consider this.
It might be worth replacing the loop with:
for(int i = strlen(str); i > 0; i--) {/* do stuff on i-th elem */}.
Here length of the string will be evaluated only once.
Of course, in the first loop the problem can be avoided as well by using additional variable to hold the length of the string but it's just an unnecessary noise, not related to the program logic.
The most obvious answer is: which one has the semantics you want? They
visit the objects in a different order.
As a general rule, if there are no other considerations, people expect
ascending order, and this is what you should use when visiting objects.
In C++, it is far more idiomatic to use iterators for this. Normal
iterators visit in ascending order, reverse iterators in descending. If
you don't explicitly need descending, you should use normal iterators.
This is what people expect, and when you do use reverse iterators, the
first thing a reader will ask is why. Also, I haven't measured, but it
wouldn't surprise me if normal iterators were faster than reverse
iterators. In Java, iterators are also idiomatic, and you don't have
reverse iterators.
If I do need descending order when visiting, I'll use a while loop (if I
don't have reverse iterators, which do it for me); I find something
like:
int index = numberOfElements;
while ( index != 0 ) {
-- index;
// ...
}
far more readable (and easier to get right) than any of the
alternatives.
If you're not visiting objects, but just counting, descending order
seems more natural to me: the control variable contains the number of
times left. And since the count is never used as an index, there's no
problem with the fact that it would be one off as an index, and you can
use a traditional for.
for ( int count = numberOfTimes; count != 0; -- count ) {
// ...
}
But it's really a question of style; I've seen a lot of ascending loops
for this as well.
The incremental for loop or decremented for loop is opted based on the way you want to use the counter variable or how good it looks
if you are accessing some array in ascending order, decremented for loop will be used
for (i = 0; i < 5; i++)
{
arr[i];
}
if you are accessing some array or list in descending order, incremental for loop is used
for (i = 5; i > 0 ; i--)
{
arr[i-1];
}
if the counter number has no significance for the value that is accessed, then readability of code is looked on. And incremental for loop looks more eye pleasing.
I would say the loop with i++ is easier to understand. Also, going backwards can make a suboptimal use of the processor cache, but usually compilers/ virtual machines are smarter than that.
I believe most programmers would be able to understand your code more quickly using the first method (i++). Unless you have the need to process an array in reverse I would stick with your first method. As for performance, I believe there would be little or no benefit to either solution.
Also you may want to consider using the for..each (enhanced for) syntax, which is quite tidier.
int[] x = {1,2,3,4,5};
for(int y: x){
System.out.println(y);
}

Array access optimization

I have a 10x10 array in Java, some of the items in array which are not used, and I need to traverse through all elements as part of a method. What Would be better to do :
Go through all elements with 2 for loops and check for the nulltype to avoid errors, e.g.
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
if(array[x][y]!=null)
//perform task here
}
}
Or would it be better to keep a list of all the used addresses... Say an arraylist of points?
Something different I haven't mentioned.
I look forward to any answers :)
Any solution you try needs to be tested in controlled conditions resembling as much as possible the production conditions. Because of the nature of Java, you need to exercise your code a bit to get reliable performance stats, but I'm sure you know that already.
This said, there are several things you may try, which I've used to optimize my Java code with success (but not on Android JVM)
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
if(array[x][y]!=null)
//perform task here
}
}
should in any case be reworked into
for(int x=0;x<10;x++){
for(int y=0;y<10;y++){
if(array[x][y]!=null)
//perform task here
}
}
Often you will get performance improvement from caching the row reference. Let as assume the array is of the type Foo[][]:
for(int x=0;x<10;x++){
final Foo[] row = array[x];
for(int y=0;y<10;y++){
if(row[y]!=null)
//perform task here
}
}
Using final with variables was supposed to help the JVM optimize the code, but I think that modern JIT Java compilers can in many cases figure out on their own whether the variable is changed in the code or not. On the other hand, sometimes this may be more efficient, although takes us definitely into the realm of microoptimizations:
Foo[] row;
for(int x=0;x<10;x++){
row = array[x];
for(int y=0;y<10;y++){
if(row[y]!=null)
//perform task here
}
}
If you don't need to know the element's indices in order to perform the task on it, you can write this as
for(final Foo[] row: array){
for(final Foo elem: row
if(elem!=null)
//perform task here
}
}
Another thing you may try is to flatten the array and store the elements in Foo[] array, ensuring maximum locality of reference. You have no inner loop to worry about, but you need to do some index arithmetic when referencing particular array elements (as opposed to looping over the whole array). Depending on how often you do it, it may or not be beneficial.
Since most of the elements will be not-null, keeping them as a sparse array is not beneficial for you, as you lose locality of reference.
Another problem is the null test. The null test itself doesn't cost much, but the conditional statement following it does, as you get a branch in the code and lose time on wrong branch predictions. What you can do is to use a "null object", on which the task will be possible to perform but will amount to a non-op or something equally benign. Depending on the task you want to perform, it may or may not work for you.
Hope this helps.
You're better off using a List than an array, especially since you may not use the whole set of data. This has several advantages.
You're not checking for nulls and may not accidentally try to use a null object.
More memory efficient in that you're not allocating memory which may not be used.
For a hundred elements, it's probably not worth using any of the classic sparse array
implementations. However, you don't say how sparse your array is, so profile it and see how much time you spend skipping null items compared to whatever processing you're doing.
( As Tom Hawtin - tackline mentions ) you should, when using an array of arrays, try to loop over members of each array rather than than looping over the same index of different arrays. Not all algorithms allow you to do that though.
for ( int x = 0; x < 10; ++x ) {
for ( int y = 0; y < 10; ++y ) {
if ( array[x][y] != null )
//perform task here
}
}
or
for ( Foo[] row : array ) {
for ( Foo item : row ) {
if ( item != null )
//perform task here
}
}
You may also find it better to use a null object rather than testing for null, depending what the complexity of the operation you're performing is. Don't use the polymorphic version of the pattern - a polymorphic dispatch will cost at least as much as a test and branch - but if you were summing properties having an object with a zero is probably faster on many CPUs.
double sum = 0;
for ( Foo[] row : array ) {
for ( Foo item : row ) {
sum += item.value();
}
}
As to what applies to android, I'm not sure; again you need to test and profile for any optimisation.
Holding an ArrayList of points would be "over engineering" the problem. You have a multi-dimensional array; the best way to iterate over it is with two nested for loops. Unless you can change the representation of the data, that's roughly as efficient as it gets.
Just make sure you go in row order, not column order.
Depends on how sparse/dense your matrix is.
If it is sparse, you better store a list of points, if it is dense, go with the 2D array. If in between, you can have a hybrid solution storing a list of sub-matrices.
This implementation detail should be hidden within a class anyway, so your code can also anytime convert between any of these representations.
I would discourage you from settling on any of these solutions without profiling with your real application.
I agree an array with a null test is the best approach unless you expect sparsely populated arrays.
Reasons for this:
1- More memory efficient for dense arrays (a list needs to store the index)
2- More computationally efficient for dense arrays (You need only compare the value you just retrieved to NULL, instead of having to also get the index from memory).
Also, a small suggestion, but in Java especially you are often better off faking a multi dimensional array with a 1D array where possible (square/rectangluar arrays in 2D). Bounds checking only happens once per iteration, instead of twice. Not sure if this still applies in the android VMs, but it has traditionally been an issue. Regardless, you can ignore it if the loop is not a bottleneck.

Categories