CALL GLOP()
Andy Malakov software blog
Monday, December 5, 2011
Monday, October 11, 2010
ShouldNotReachHere
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (classFileParser.cpp:3161), pid=3136, tid=4676
# Error: ShouldNotReachHere()
#
Sunday, October 3, 2010
My first Android app

I created my first Android app. It converts a date in Gregorian Calendar into Maya "Long Count" calendar. Contrary to popular view Mayan calendar doesn't end on December 21st, 2012. You can test this in my app :-).
Sources can be found here.
Sunday, June 6, 2010
Alternative to Thread.sleep()
private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(2); //TODO: Determine for current machine
public static void sleepNanos (long nanoDuration) throws InterruptedException {
final long end = System.nanoTime() + nanoDuration;
long timeLeft = nanoDuration;
do {
if (timeLeft > SLEEP_PRECISION)
Thread.sleep (1);
else
Thread.sleep (0); // Thread.yield();
timeLeft = end - System.nanoTime();
if (Thread.interrupted())
throw new InterruptedException ();
} while (timeLeft > 0);
}
Test
I run 4 threads requesting 5 millisecond sleep 1000 times each (on my Dual-Core CPU). The first chart shows sleepNanos(TimeUnit.MILLISECONDS(5).toNanos()):

The second chart shows Thread.sleep(5):

As you can see, sleepNanos() is much more precise. I found that this approach was originally used by Ryan Geiss for WinAmp visualization plugin.
UPDATE
Even better precision can be achieved if you are willing to consume more CPU power doing Spin-Wait for the last part of the wait:
public static void sleepNanos (long nanoDuration) throws InterruptedException {
final long end = System.nanoTime() + nanoDuration;
long timeLeft = nanoDuration;
do {
if (timeLeft > SLEEP_PRECISION)
Thread.sleep (1);
else
if (timeLeft > SPIN_YIELD_PRECISION)
Thread.sleep(0);
timeLeft = end - System.nanoTime();
if (Thread.interrupted())
throw new InterruptedException ();
} while (timeLeft > 0);
}
Thursday, May 13, 2010
Measuring nanoseconds in Java / Windows
I was under false impression that interval timers in Java allow sub-millisecond precision on Windows. I knew that Thread.sleep(millis, nanos) internally uses milliseconds, but for some reason I thought that methods like LockSupport.parkNanos() method provide precise waits. Well, I was wrong. The smallest delay this method can realize is approximately 1.95 milliseconds on my Windows PC.
Back in 2006 David Holmes explained that Java timer intervals are based on waitForMultipleObjects() Windows API (which uses dwMilliseconds). They still are.
One simple (but not universal) workaround is a "spin-sleep":
private static void sleepNanos (long nanoDelay) {
final long end = System.nanoTime() + nanoDelay;
do {
Thread.yield(); // Thread.sleep (0);
} while (System.nanoTime() < end);
}
When running standalone this method consumes all free resources of single CPU core, but it will share with other threads that may be running. For large durations it can be enhanced to use Thread.sleep() for bulk of the waiting.
P.S. Difference between Thread.yield() and Thread.sleep( 0 ) is explained here.
Friday, December 11, 2009
Old trap
class Foo {
private long id;
private String name;
Foo(long id, String name) {
this.id = id;
this.name = name;
}
public String toString () {
return id + ' ' + name;
}
}
The statement new Foo(123, "Hello") prints something like "155Hello" instead of "123 Hello". Of course the reason is pretty simple:
public String toString2() {
return new StringBuilder().append(id + 32L).append(name.toString()).toString();
}
Wednesday, November 11, 2009
Stack allocation in Java is still a myth
There were rumors that Mustang will have on stack allocation as a part of hot spot optimization.
Four+ years later this :
public long encode (String input) {
final byte [] buffer = new byte [8];
.. encode input into buffer
.. convert buffer into LONG
return result;
}
I was hoping JVM will allocate buffer on stack based on the fact that it does not escape from this method. Running this test 10M times with -verbosegc shows extensive GC work (1.6.0_16-b01 64 bit server JVM with -XX:+DoEscapeAnalysis option).
On the positive side. GC is very fast. Consider three functions:
- encodeNewBuffer () uses new byte array to encode input string.
- encodeSynchronizedField () uses private field, guarded by synchronized{} block
- encodeThreadLocalField () uses ThreadLocal cache to encode input string
Here is the code:
long encodeNewBuffer (String input) {
final byte [] buffer = new byte [8];
return f (buffer);
}
/////////////
private final byte [] buffer = new byte [8];
synchronized long encodeSynchronizedField (String input) {
return f (buffer);
}
/////////////
ThreadLocal<byte[]> threadLocal = new ThreadLocal<byte[]>();
{
threadLocal.set(new byte [8]);
}
long encodeThreadLocalField (String input) {
byte [] buffer = threadLocal.get();
return f (buffer);
}
GC-based method is a winner:
encodeNewBuffer(): 4,108 sec.
encodeSynchronizedField(): 5,322 sec.
encodeThreadLocalField() : 5,411 sec
Monday, November 9, 2009
Multi-threaded testing with JUnit. Switch to ConcJUnit .
Lets consider a simple thread that interprets commands from input queue. In this example it can only understand "exit" command. All other inputs trigger an error.
abstract class MainLoop extends Thread {
private Queue<String> commands = new LinkedBlockingDeque<String>();
public void run () {
while (true) {
String command = commands.poll();
if (command.equals ("exit"))
break;
else
reportError ("Unknown command: " + command);
}
}
public void add (String command) {
commands.add(command);
}
abstract void reportError (String error);
}
public class MyTest {
@Test
public void test() {
MainLoop thread = new MainLoop() {
void reportError(String error) {
Assert.fail (error);
}
};
thread.start();
thread.add ("quit"); // sic! shoudl be "exit"
}
}
If we run the above test, JUnit completely ignores failure of "Commands Interpreter" thread (Although default uncaughtExceptionHandler prints exception to standard output):
[junit] Running test.MyTest
[junit] Exception in thread "Commands Interpreter": java.lang.AssertionError: Unknown command: quit
[junit] at org.junit.Assert.fail(Assert.java:91)
[junit] at test.MyTest$1.reportError(MyTest.java:36)
[junit] at test.MainLoop.run(MyTest.java:19)
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.422 sec
As you can see JUnit detected 0 errors. JUnit has at least two problems when it comes to multi-threaded tests:
- JUnit only cares about errors in its own thread. It completely ignores exceptions or assertion failures in child threads.
- Left over child threads may produce side effect on subsequent tests. In some cases failures in child threads may happen after the main thread is finished.
We used various custom workarounds until it was clear that we need a generic solution for growing number of multi-threaded tests. Luckily we found an excellent tool - ConcJUnit (AKA ConcuTest) written by Mathias Ricken.
a) ConcJUnit is a drop-in replacement of JUnit. It includes standard JUnit classes and introduces own test runners. Just replace junit.jar by concutest.jar .
b) ConcJUnit detects both failures in child threads and leftover threads.
Switching to ConcJUnit produces expected result:
java.lang.AssertionError: Unknown command: quit
at org.junit.Assert.fail(Assert.java:91)
at test.MyTest$1.reportError(MyTest.java:36)
at test.MainLoop.run(MyTest.java:19)
at test.MainLoop.run(MyTest.java:19)
If you want to know more about ConcJUnit, read materials from introduction page. For example, the following presentation.
Thursday, November 5, 2009
GLOP
GLOPand we are done! Not only are we finished, but we are relatively certain that the resulting program is correct — assuming that the hardware primitive GLOP performs correctly (and if it doesn't, we can always blame it on the vendor)."
Edward Yourdon "Techniques of program structure and design" 1975.
Tuesday, November 3, 2009
Blog Archive
- December 2011 (1)
- October 2010 (2)
- June 2010 (1)
- May 2010 (1)
- December 2009 (1)
- November 2009 (4)
- October 2009 (1)
- July 2009 (2)
- June 2009 (1)
- December 2008 (1)
- September 2008 (2)
- August 2008 (4)
- July 2008 (3)
- June 2008 (4)
- May 2008 (1)