This Program should do this
N 10*N 100*N 1000*N
1 10 100 1000
2 20 200 2000
3 30 300 3000
4 40 400 4000
5 50 500 5000
So here's my code:
public class ex_4_21 {
public static void main( String Args[] ){
int process = 1;
int process2 = 1;
int process22 = 1;
int process3 = 1;
int process33 = 2;
System.out.println("N 10*N 100*N 1000*N");
while(process<=5){
while(process2<=3){
System.out.printf("%d ",process2);
while(process22<=3){
process2 = process2 * 10;
System.out.printf("%d ",process2);
process22++;
}
process2++;
}
process++;
}
}
}
Can my code be more effecient? I am currently learning while loops. So far this what I got. Can anyone make this more efficient, or give me ideas on how to make my code more efficient?
This is not a homework, i am self studying java
You can use a single variable n to do this.
while(n is less than the maximum value that you wish n to be)
print n and a tab
print n * 10 and a tab
print n * 100 and a tab
print n * 1000 and a new line
n++
if the power of 10 is variable then you can try this:
while(n is less than the maximum value that you wish n to be)
while(i is less than the max power of ten)
print n * i * 10 and a tab
i++
print a newline
n++
If you must use a while loop
public class ex_4_21 {
public static void main( String Args[] ){
int process = 1;
System.out.println("N 10*N 100*N 1000*N");
while(process<=5){
System.out.println(process + " " + 10*process + " " + 100*process + " " + 1000*process + "\n");
process++;
}
}
}
You have one too many while loops (your "process2" while loop is unnecessary). You also appear to have some bugs related to the fact that the variables you are looping on in the inner loops are not re-initialized with each iteration.
I would also recommend against while loops for this; Your example fits a for loop much better; I understand you are trying to learn the looping mechanism, but part of learning should also be in deciding when to use which construct. This really isn't a performance recommendation, more an approach recommendation.
I don't have any further performance improvement suggestions, for what you are trying to do; You could obviously remove loops (dropping down to a single or even no loops), but two loops makes sense for what you are doing (allows you to easily add another row or column to the output with minimal changes).
You can try loop unrolling, similar to #Vincent Ramdhanie's answer.
However, loop unrolling and threading won't produce a significant performance improvement for such a small sample. The overhead involved in creating and launching threads (processes) takes more time than a simple while loop. The overhead in I/O will take more time than the unrolled version saves. A complex program is harder to debug and maintain than a simple one.
You're thinking is called microoptimization. Save the optimizations for larger programs and only when the requirements cannot be met or the customer(s) demand so.
Related
I implemented a basic sorting algorithm in Java, and compared its performance to those of native methods (Arrays.sort() and Arrays.parallelSort()). The program is as follows.
public static void main(String[] args) {
// Randomly populate array
int[] array = new int[999999];
for (int i = 0; i < 999999; i++)
array[i] = (int)Math.ceil(Math.random() * 100);
long start, end;
start = System.currentTimeMillis();
Arrays.sort(array);
end = System.currentTimeMillis();
System.out.println("======= Arrays.sort: done in " + (end - start) + " ms ========");
start = System.currentTimeMillis();
Arrays.parallelSort(array);
end = System.currentTimeMillis();
System.out.println("======= Arrays.parallelSort: done in " + (end - start) + " ms ========");
start = System.currentTimeMillis();
orderArray(array);
end = System.currentTimeMillis();
System.out.println("======= My way: done in " + (end - start) + " ms ========");
}
private static int[] orderArray(int[] arrayToOrder) {
for (int i = 1; i < arrayToOrder.length; i++) {
int currentElementIndex = i;
while (currentElementIndex > 0 && arrayToOrder[currentElementIndex] < arrayToOrder[currentElementIndex-1]) {
int temp = arrayToOrder[currentElementIndex];
arrayToOrder[currentElementIndex] = arrayToOrder[currentElementIndex-1];
arrayToOrder[currentElementIndex-1] = temp;
currentElementIndex--;
}
}
return arrayToOrder;
}
When I run this program, my custom algorithm consistently outperforms the native queries, by orders of magnitude, on my machine. Here is a representative output I got:
======= Arrays.sort: done in 67 ms ========
======= Arrays.parallelSort: done in 26 ms ========
======= My way: done in 4 ms ========
This is independent of:
The number of elements in the array (999999 in my example)
The number of times the sort is performed (I tried inside a for loop and iterated a large number of times)
The data type (I tried with an array of double instead of int and saw no difference)
The order in which I call each ordering algorithm (does not affect the overall difference of performance)
Obviously, there's no way my algorithm is actually better than the ones provided with Java. I can only think of two possible explanations:
There is a flaw in the way I measure the performance
My algorithm is too simple and is missing some corner cases
I expect the latter is true, seen as I used a fairly standard way of measuring performance with Java (using System.currentTimeMillis()). However, I have extensively tested my algorithm and can find no fallacies as of yet - an int has predefined boundaries (Integer.MIN_VALUE and MAX_VALUE) and cannot be null, I can't think of any possible corner case I've not covered.
My algorithm's time complexity (O(n^2)) and the native methods' (O(n log(n)))), which could obviously cause an impact. Again, however, I believe my complexity is sufficient...
Could I get an outsider's look on this, so I know how I can improve my algorithm?
Many thanks,
Chris.
You're sorting an array in place, but you didn't re-scramble the array between each trail. This means you're sorting the best case scenario. In between each call to to an array sorting method you can re-create the array.
for (int i = 0; i < TEST_SIZE; i++)
array[i] = (int)Math.ceil(Math.random() * 100);
After doing this you will notice your algorithm is about 100 times slower.
That said, this is not the best way to compare the methods in the first place. At a minimum you should be sorting the same original array for each different algorithm. You should also perform multiple iterations over each algorithm and average the response. The result from a single trial will be spurious and not reliable as a good comparison.
Alright so I was working on a game in Eclipse Neon and I noticed that when I added a break statement to the program it significantly slowed down the programs speed from around 120 fps to 80 fps(which makes little sense). So I decided to test it out in another class and got similar results.
This is the code I ran:
public static int[] xArray = new int[100000];
public static int[] yArray = new int[10000];
public static void main(String[] args){
long timeStart = System.currentTimeMillis();
int numberOfLoops = 0;
int uboveMax = 0;
for(int x = 0; x < xArray.length; x++){
for(int y = 0; y < yArray.length; y++){
numberOfLoops++;
if(y > 9000){
uboveMax++;
//break;
}
}
}
long timeTaken = System.currentTimeMillis();
System.out.println("Number of Loops: " + numberOfLoops);
System.out.println("Ubove Max: " + uboveMax);
System.out.println("Time Taken(MS): " + (timeTaken - timeStart));
}
So when I ran the code (in Eclipse Neon 2 (4.6.2)) I got unexpected results:
With the break statement: Time Taken(MS): 344.8 (average from 5 tests)
Without the break statement: Time Taken(MS): 294.6 (average from 5 tests)
Then when I ran the code (in NetBeans IDE 8.2) I got expected results:
With the break statement: Time Taken(MS): 4.2 (average from 5 tests)
Without the break statement: Time Taken(MS): 556.8 (average from 5 tests)
Shouldn't the code (in Eclipse) with the break statement be running at least the same speed if not even faster? Also what is the cause of the large discrepancy between Eclipse and NetBeans, I know they are very different programs, but don't both run the code from the same JVM, is their something wrong with the Eclipse compiler? If anyone could provide an explanation for this occurrence that would be great, thanks!
This should better be a comment, but it's too long. The problem with your code is that what it does is equivalent to
System.out.println("Number of Loops: " + 1000000000);
System.out.println("Ubove Max: " + 99900000);
This could be optimized down to a few cycles. This doesn't happen as you don't give the JVM enough time and/or because of OSR (see this question for a good example).
You code (without break) could be optimized to
for(int x = 0; x < xArray.length; x++) {
numberOfLoops += yArray.length;
uboveMax += Math.max(0, yArray.length - 9001);
}
and further to
numberOfLoops += xArray.length * yArray.length;
uboveMax += xArray.length * Math.max(0, yArray.length - 9001);
The code using break would lead to a similar expression. If I was the JVM, I'd be upset with you wasting time on such a non-sense. The JVM isn't upset, and if you'd gave it a chance, you'd see times close to zero in both cases. It's possible but improbable, that (even given enough time) one of the cases doesn't get optimized as well as the other, but this is nothing essential, it's just that there are countless optimization possibilities and there are cases when the JVM misses something.
IMHO, this example will not give you any insight to why the slowdown happens with your real code. simplifying code in order to locate the problem is good, but you went too far. In reality, your variables do something and probably influence the future computation in way so that breaking out of the loop cases more work to be done in the future. Just guessing, but what else without the real code?
So I have a problem I've been wracking my brain over for about a week now. The situation is:
Consider a checkout line at the grocery store. During any given
second, the probability that a new customer joins the line is 0.02 (no
more than one customer joins the line during any given second). The
checkout clerk takes a random amount of time between 20 seconds to 75
seconds to serve each customer. Write a program to simulate this
scenario for about ten million seconds and print out the average
number of seconds that a customer spends waiting in line before the
clerk begins to serve the customer. Note that since you do not know
the maximum number of customers that may be in line at any given time,
you should use an ArrayList and not an array.
The expected average wait time is supposed to be between 500 and 600 seconds. However, I have not gotten an answer anywhere close to this range. Given that the probability of a new customer in the line is only 2%, I would expect the line to never have more than 1 person in it, so the average wait time would be about 45-50 secs. I have asked a friend (who is a math major) what his view on this problem, and he agreed that 45 seconds is a reasonable average given the 2% probability. My code so far is:
package grocerystore;
import java.util.ArrayList;
import java.util.Random;
public class GroceryStore {
private static ArrayList<Integer> line = new ArrayList();
private static Random r = new Random();
public static void addCustomer() {
int timeToServe = r.nextInt(56) + 20;
line.add(timeToServe);
}
public static void removeCustomer() {
line.remove(0);
}
public static int sum(ArrayList<Integer> a) {
int sum = 0;
for (int i = 0; i < a.size(); i++) {
sum += a.get(i);
}
return sum;
}
public static void main(String[] args) {
int waitTime = 0;
int duration = 10000;
for (int i = 0; i < duration; i++) {
double newCust = r.nextDouble();
if (newCust < .02) {
addCustomer();
}
try {
for (int j = 0; j < line.get(0); j++) {
waitTime = waitTime + sum(line);
}
} catch (IndexOutOfBoundsException e) {}
if (line.isEmpty()) {}
else {
removeCustomer();
}
}
System.out.println(waitTime/duration);
}
}
Any advice about this would be appreciated.
Here's some pseudocode to help you plan it out
for each second that goes by:
generate probability
if probability <= 0.02
add customer
if wait time is 0
if line is not empty
remove customer
generate a new wait time
else
decrement wait time
There's actually a very easy implementation of single server queueing systems where you don't need an ArrayList or Queue to stash customers who are in line. It's based on a simple recurrence relation described below.
You need to know the inter-arrival times' distribution, i.e., the distribution of times between one arrival and the next. Yours was described in time-stepped fashion as a probability of 0.02 of having a new arrival in a given tick of the clock. That equates to a Geometric distribution with p = 0.02. You already know the service time distribution - Uniform(20,75).
With those two pieces of info, and a bit of thought, you can deduce that for any given customer the arrival time is the previous customer's arrival-time plus a (generated) interarrival time; this customer can begin being served at either their arrival-time or the departure-time of the prior customer, whichever comes later; and they finish up with the server and depart at their begin-service time plus a (generated) service-time. You'll need to initialize the arrival-time and departure time of an imaginary zeroth customer to kick-start the whole thing, but then it's a simple loop to calculate the recurrence.
Since this looks like homework I'm giving you an implementation in Ruby. If you don't know Ruby, think of this as pseudo-code. It should be very straightforward for you to translate to Java. I've left out details such as how to generate the distributions, but I have actually run the complete implementation of this, replacing the commented lines with statistical tallies, and it gives average wait times around 500.
interarrival_time = Geometric.new(p_value)
service_time = Uniform.new(service_min, service_max)
arrival_time = depart_time = 0.0 # initialize zeroth customer
loop do
arrival_time += interarrival_time.generate
break if arrival_time > 10_000_000
start_time = [arrival_time, depart_time].max
depart_time = start_time + service_time.generate
delay_in_queue = start_time - arrival_time
# do anything you want with the delay_in_queue value:
# print it, tally it for averaging, whatever...
end
Note that this approach skips over the large swathes of time where nothing is happening, so it's a quite efficient little program compared to time-stepping through every tick of the simulated clock and storing things in dynamically sized containers.
One final note - you may want to ignore the first few hundred or thousand observations due to initialization bias. Simulation models usually need a "warm-up" period to remove the effect of the programmatically necessary initialization of variables to arbitrary values.
Instead of using an ArrayList, a Queue might be better suited for managing the customers. Also, remove the try/catch clause and a throws IndexOutOfBoundsException to the main function definition.
There are many questions and answers and opinions about how to do low level Java optimization, with for, while, and do-while loops, and whether it's even necessary.
My question is more of a High Level based optimization in design. Let's assume I have to do the following:
for a given string input, count the occurrence of each letter in the string.
this is not a major problem when the string is a few sentences, but what if instead we want to count the occurrence of each word in a 900,000 word file. building loops just wastes time.
So what is the high level design pattern that can be applied to this type of problem.
I guess my major point is that I tend to use loops to solve many problems, and I would like to get out of the habit of using loops.
thanks in advance
Sam
p.s. If possible can you produce some pseudo code for solving the 900,000 word file problem, I tend to understand code better than I can understand English, which I assume is the same for most visitors of this site
The word count problem is one of the most widely covered problems in the Big Data world; it's kind of the Hello World of frameworks like Hadoop. You can find ample information throughout the web on this problem.
I'll give you some thoughts on it anyway.
First, 900000 words might still be small enough to build a hashmap for, so don't discount the obvious in-memory approach. You said pseudocode is fine, so:
h = new HashMap<String, Integer>();
for each word w picked up while tokenizing the file {
h[w] = w in h ? h[w]++ : 1
}
Now once your dataset is too large to build an in-memory hashmap, you can do your counting like so:
Tokenize into words writing each word to a single line in a file
Use the Unix sort command to produce the next file
Count as you traverse the sorted file
These three steps go in a Unix pipeline. Let the OS do the work for you here.
Now, as you get even more data, you want to bring in map-reduce frameworks like hadoop to do the word counting on clusters of machines.
Now, I've heard when you get into obscenely large datasets, doing things in a distributed enviornment does not help anymore, because the transmission time overwhelms the counting time, and in your case of word counting, everything has to "be put back together anyway" so then you have to use some very sophisticated techniques that I suspect you can find in research papers.
ADDENDUM
The OP asked for an example of tokenizing the input in Java. Here is the easiest way:
import java.util.Scanner;
public class WordGenerator {
/**
* Tokenizes standard input into words, writing each word to standard output,
* on per line. Because it reads from standard input and writes to standard
* output, it can easily be used in a pipeline combined with sort, uniq, and
* any other such application.
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
System.out.println(input.next().toLowerCase());
}
}
}
Now here is an example of using it:
echo -e "Hey Moe! Woo\nwoo woo nyuk-nyuk why soitenly. Hey." | java WordGenerator
This outputs
hey
moe!
woo
woo
woo
nyuk-nyuk
why
soitenly.
hey.
You can combine this tokenizer with sort and uniq like so:
echo -e "Hey Moe! Woo\nwoo woo nyuk-nyuk why soitenly. Hey." | java WordGenerator | sort | uniq
Yielding
hey
hey.
moe!
nyuk-nyuk
soitenly.
why
woo
Now if you only want to keep letters and throw away all punctuation, digits and other characters, change your scanner definition line to:
Scanner input = new Scanner(System.in).useDelimiter(Pattern.compile("\\P{L}"));
And now
echo -e "Hey Moe! Woo\nwoo woo^nyuk-nyuk why#2soitenly. Hey." | java WordGenerator | sort | uniq
Yields
hey
moe
nyuk
soitenly
why
woo
There is a blank line in the output; I'll let you figure out how to whack it. :)
The fastest solution to this is O(n) AFAIK use a loop to iterate the string, get the character and update the count in a HashMap accordingly. At the end the HashMap contains all the characters that occurred and a count of all the occurrences.
Some pseduo-code (may not compile)
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (map.containsKey(c)) map.put(c, map.get(c) + 1);
else map.put(c, 1);
}
It's hard for you to get much better than using a loop to solve this problem. IMO, the best way to speed up this sort of operation is to split the workload into different units of work and process the units of work with different processors (using threads, for example, if you have a multiprocessor computer).
You shouldn't assume 900,000 is a lot of words. If you have a CPU with 8 threads and 3 GHZ that's 24 billion clock cycles per second. ;)
However for counting characters using an int[] will be much faster. There is only 65,536 possible characters.
StringBuilder words = new StringBuilder();
Random rand = new Random();
for (int i = 0; i < 10 * 1000 * 1000; i++)
words.append(Long.toString(rand.nextLong(), 36)).append(' ');
String text = words.toString();
long start = System.nanoTime();
int[] charCount = new int[Character.MAX_VALUE];
for (int i = 0; i < text.length(); i++)
charCount[text.charAt(i)]++;
long time = System.nanoTime() - start;
System.out.printf("Took %,d ms to count %,d characters%n", time / 1000/1000, text.length());
prints
Took 111 ms to count 139,715,647 characters
Even 11x times the number of words takes a fraction of a second.
A much longer parallel version is a little faster.
public static void main(String... args) throws InterruptedException, ExecutionException {
StringBuilder words = new StringBuilder();
Random rand = new Random();
for (int i = 0; i < 10 * 1000 * 1000; i++)
words.append(Long.toString(rand.nextLong(), 36)).append(' ');
final String text = words.toString();
long start = System.nanoTime();
// start a thread pool to generate 4 tasks to count sections of the text.
final int nThreads = 4;
ExecutorService es = Executors.newFixedThreadPool(nThreads);
List<Future<int[]>> results = new ArrayList<Future<int[]>>();
int blockSize = (text.length() + nThreads - 1) / nThreads;
for (int i = 0; i < nThreads; i++) {
final int min = i * blockSize;
final int max = Math.min(min + blockSize, text.length());
results.add(es.submit(new Callable<int[]>() {
#Override
public int[] call() throws Exception {
int[] charCount = new int[Character.MAX_VALUE];
for (int j = min; j < max; j++)
charCount[text.charAt(j)]++;
return charCount;
}
}));
}
es.shutdown();
// combine the results.
int[] charCount = new int[Character.MAX_VALUE];
for (Future<int[]> resultFuture : results) {
int[] result = resultFuture.get();
for (int i = 0, resultLength = result.length; i < resultLength; i++) {
charCount[i] += result[i];
}
}
long time = System.nanoTime() - start;
System.out.printf("Took %,d ms to count %,d characters%n", time / 1000 / 1000, text.length());
}
prints
Took 45 ms to count 139,715,537 characters
But for a String with less than a million words its not likely to be worth it.
As a general rule, you should just write things in a straightforward way, and then do performance tuning to make it as fast as possible.
If that means putting in a faster algorithm, do so, but at first, keep it simple.
For a small program like this, it won't be too hard.
The essential skill in performance tuning is not guessing.
Instead, let the program itself tell you what to fix.
This is my method.
For more involved programs, like this one, experience will show you how to avoid the over-thinking that ends up causing a lot of the poor performance it is trying to avoid.
You have to use divide and conquer approach and avoid race for resources. There are different approaches and/or implementations for that. The idea is the same - split the work and parallelize the processing.
On single machine you can process chunks of the data in separate threads, although having the chunks on the same disk will slow things down considerably. H having more threads means having more context-switching, for throughput is IMHO better to have smaller amount of them and keep them busy.
You can split the processing to stages and use SEDA or something similar and with really big data you do for map-reduce - just count with the expense of distributing data across cluster.
I'll be glad of somebody point to another widely-used API.
I have created a class to handle my debug outputs so that I don't need to strip out all my log outputs before release.
public class Debug {
public static void debug( String module, String message) {
if( Release.DEBUG )
Log.d(module, message);
}
}
After reading another question, I have learned that the contents of the if statement are not compiled if the constant Release.DEBUG is false.
What I want to know is how much overhead is generated by running this empty method? (Once the if clause is removed there is no code left in the method) Is it going to have any impact on my application? Obviously performance is a big issue when writing for mobile handsets =P
Thanks
Gary
Measurements done on Nexus S with Android 2.3.2:
10^6 iterations of 1000 calls to an empty static void function: 21s <==> 21ns/call
10^6 iterations of 1000 calls to an empty non-static void function: 65s <==> 65ns/call
10^6 iterations of 500 calls to an empty static void function: 3.5s <==> 7ns/call
10^6 iterations of 500 calls to an empty non-static void function: 28s <==> 56ns/call
10^6 iterations of 100 calls to an empty static void function: 2.4s <==> 24ns/call
10^6 iterations of 100 calls to an empty non-static void function: 2.9s <==> 29ns/call
control:
10^6 iterations of an empty loop: 41ms <==> 41ns/iteration
10^7 iterations of an empty loop: 560ms <==> 56ns/iteration
10^9 iterations of an empty loop: 9300ms <==> 9.3ns/iteration
I've repeated the measurements several times. No significant deviations were found.
You can see that the per-call cost can vary greatly depending on workload (possibly due to JIT compiling),
but 3 conclusions can be drawn:
dalvik/java sucks at optimizing dead code
static function calls can be optimized much better than non-static
(non-static functions are virtual and need to be looked up in a virtual table)
the cost on nexus s is not greater than 70ns/call (thats ~70 cpu cycles)
and is comparable with the cost of one empty for loop iteration (i.e. one increment and one condition check on a local variable)
Observe that in your case the string argument will always be evaluated. If you do string concatenation, this will involve creating intermediate strings. This will be very costly and involve a lot of gc. For example executing a function:
void empty(String string){
}
called with arguments such as
empty("Hello " + 42 + " this is a string " + count );
10^4 iterations of 100 such calls takes 10s. That is 10us/call, i.e. ~1000 times slower than just an empty call. It also produces huge amount of GC activity. The only way to avoid this is to manually inline the function, i.e. use the >>if<< statement instead of the debug function call. It's ugly but the only way to make it work.
Unless you call this from within a deeply nested loop, I wouldn't worry about it.
A good compiler removes the entire empty method, resulting in no overhead at all. I'm not sure if the Dalvik compiler already does this, but I suspect it's likely, at least since the arrival of the Just-in-time compiler with Froyo.
See also: Inline expansion
In terms of performance the overhead of generating the messages which get passed into the debug function are going to be a lot more serious since its likely they do memory allocations eg
Debug.debug(mymodule, "My error message" + myerrorcode);
Which will still occur even through the message is binned.
Unfortunately you really need the "if( Release.DEBUG ) " around the calls to this function rather than inside the function itself if your goal is performance, and you will see this in a lot of android code.
This is an interesting question and I like #misiu_mp analysis, so I thought I would update it with a 2016 test on a Nexus 7 running Android 6.0.1. Here is the test code:
public void runSpeedTest() {
long startTime;
long[] times = new long[100000];
long[] staticTimes = new long[100000];
for (int i = 0; i < times.length; i++) {
startTime = System.nanoTime();
for (int j = 0; j < 1000; j++) {
emptyMethod();
}
times[i] = (System.nanoTime() - startTime) / 1000;
startTime = System.nanoTime();
for (int j = 0; j < 1000; j++) {
emptyStaticMethod();
}
staticTimes[i] = (System.nanoTime() - startTime) / 1000;
}
int timesSum = 0;
for (int i = 0; i < times.length; i++) { timesSum += times[i]; Log.d("status", "time," + times[i]); sleep(); }
int timesStaticSum = 0;
for (int i = 0; i < times.length; i++) { timesStaticSum += staticTimes[i]; Log.d("status", "statictime," + staticTimes[i]); sleep(); }
sleep();
Log.d("status", "final speed = " + (timesSum / times.length));
Log.d("status", "final static speed = " + (timesStaticSum / times.length));
}
private void sleep() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void emptyMethod() { }
private static void emptyStaticMethod() { }
The sleep() was added to prevent overflowing the Log.d buffer.
I played around with it many times and the results were pretty consistent with #misiu_mp:
10^5 iterations of 1000 calls to an empty static void function: 29ns/call
10^5 iterations of 1000 calls to an empty non-static void function: 34ns/call
The static method call was always slightly faster than the non-static method call, but it would appear that a) the gap has closed significantly since Android 2.3.2 and b) there's still a cost to making calls to an empty method, static or not.
Looking at a histogram of times reveals something interesting, however. The majority of call, whether static or not, take between 30-40ns, and looking closely at the data they are virtually all 30ns exactly.
Running the same code with empty loops (commenting out the method calls) produces an average speed of 8ns, however, about 3/4 of the measured times are 0ns while the remainder are exactly 30ns.
I'm not sure how to account for this data, but I'm not sure that #misiu_mp's conclusions still hold. The difference between empty static and non-static methods is negligible, and the preponderance of measurements are exactly 30ns. That being said, it would appear that there is still some non-zero cost to running empty methods.