Friday, January 15, 2010

Sondasplorer - A bytecode instrumentalization framework

Sondasplorer is the new personal project which I am working on.


Sondasplorer is a framework that allows us to add probes to existing classes and methods according to necessities, which let us to isolate the complexity of modifying the Java bytecode. This framework let us use existing Sondasplorer probes or even create ours in a very easy and friendly way.

Sondasplorer is designed to be extremally fast being suitable to be used in both Preproduction and Production environments. We can make similar things to commercial tools as PerformaSure and Introscope !!!

In Sondasplorer framework a probe is a Java class which purpose is to assess and/or modify any parameter in runtime. For example we can:
  • Assess methods total execution time
  • Assess methods exclusive execution time
  • Assess execution errors
  • Investigate methods calling parameters
  • Assess methods invocation count
  • Generate a performance execution tree
  • Detect memory leaks
  • Alter existing classes funcionality in a transparent way
  • What your imagination can create
For example, there exists a probe specialized in PreparedStatements that let us to assess the execution time and to view which parameters they were called with!

The probes can send the collected information to remote managers where the raw information can be processed, stored and viewed both in runtime and offline. We can have a battery of probes as our working toolkit.

The bytecode modification (instrumentalization) is realized in a dynamic and transparent way meaning that it is not neccesary to alter existing applications to add probes. We have only to indicate the classes and/or methods we want to instrumentalize and the framework will automatically modify the classes just in the time of being loaded.

Every Java application can be instrumentalized, including standalone and web applications running in application servers (Websphere, Tomcat, etc).

It is possible to enable and disable probes on demand. That allow us, for example, to enable the full-trace of a probe only when is needed and during the neccesary time. This is very useful in Preproduction environments where it is not possible to enable the full-trace mode from the beginning of a heavy test.

Following I have attached some captures of a probe I am currently developing called WebProbe that let us analyze the performance of web applications:




As you can see, we can have multiples views over the same collected data set and even better, we can define our views adapted to our necessities.

The characteristcs will be better specified in new entries.

If you consider Sondasplorer interesting, any help would be really appreciated!!


Wednesday, January 13, 2010

Atomicy in primitive types

Sometimes we can have a thread changing the state of a primitive type flag, and other threads reading it.

The correct way to proceed is to synchronize that flag using synchronized blocks or defining it as volatile to assure visibility between threads. But what about atomicy?

If we define a variable of a primitive type and make read or write actions over it without synchronizing, supposing that it were visible from other threads, would that operation be atomic? That's to say, if the primitive type is for example an integer (4 bytes), are those 4 bytes written atomically?

The answer is almost a "Yes". Internally, all primitive types but double and long are managed atomically as 4 bytes blocks. That differs from C/C++ where, depending on the platform read and write actions can or cannot be atomic. If we don't synchronize correctly in C/C++ we can read a variable of a primitive type written partially with unexpected results.


What happens with double and long primitive types?

As they are 64 bits types they can be treated by the compiler as two 32 bits read and write operations. Therefore, in case of not being synchronized correctly we could run into those same strange things that might happen in C/C++.


Any other solution besides using synchronized blocks?

Yes, we have the volatile declaration. Besides assuring visibility, if we declare a primitive type as volatile we are also assuring atomicy in read and write actions over it.

Remember that accessing volatile variables are lighter than using synchronized blocks and they never block.

Friday, January 8, 2010

Volatile Fields

Volatile fields are present from a long time but even today they are a big unknown. In times where most machines had only a processor, although possibly necessary, we could write programs without having to deal with them. But in these days, with the arrival of multiprocessor systems, volatile fields have become vital. I am not going into details as there are a lot of resources in the web about them.

Let's say that volatile fields allow us to make fields visible between thread. A situation where it can be useful is the case when a flag can be set and unset by different thread concurrently. Suppose we need to turn the debug mode on/off in runtime. We could have a global flag field accessible by all threads that read it to know if they have to print traces. For example:


class Global {
static int debugLevel = false;
static boolean debugFlag = 0;

static void turnOnDebug(int level) {
debugLevel = level;
debugFlag = true;
}

static void turnOffDebug() {
debugFlag = false;
}
}

class Worker {
void doWork() {
...
if (Global.debugFlag) {
if (level>=1) {
System.out.println("INFO: in doWork method");
}

if (level>=2) {
System.out.println("DEBUG: more detailed information");
}
}
...
}
}


What would happen if a thread calls Global.turnOnDebug(2)?

The logical answer is that all threads would start printing traces but what really happends is that it is not guaranteed that other threads see debugFlag as true.

How come?

Because of visibility of fields as debugFlag field can be cached without being placed in main memory. That implies that the other threads see an outdated value of this field.

Any other surprise?

Yes, even in case of the other threads noticed the change of the field debugFlag, they could see the level value as 0!

How come?

Because of a technique used to improve performance called reordering. In this case, when turnOnDebug is called, the compiler is free to execute the sentence setting debugFlag as true before setting debugLevel. Then, if just before setting the level another thread is scheduled and executes the doWork method, it could see the field debugFlag as true and level as 0.

Well, to solve this, we can use volatile fields. A detailed explanation using the happens-before idiom can be read in JSR133, here I will only put it in practice.

We could access this field using synchronized blocks, but it would be better in performance terms to define the debugFlag field as volatile:

volatile static boolean debugFlag = 0;

Volatile fields are a lot lighter than synchronized blocks and are guaranteed to never block.

Why?

Reads of volatile fields are guaranteed to be updated!!!
Compiler assures that the field is placed in memory (no cache) before the read is made.

Shouldn't we make debugLevel volatile as well?

We could, but it is not necessary because when a thread reads a volatile field, it is guaranteed that the values of previous fields written are updated and visible from the reader thread. That means that the new value of debugLevel is sure to be in memory after reading the volatile field and this implies that the reordering commented before cannot take place.

As said before, all described here can be expressed formally using the happens-before idiom described in JSR133 and in the Java Memory Model of recent revisions of JLS (Java Language Specification). It applies officially since Java 1.5(unofficially since latest revisions of Java 1.4). Before this version, Java Memory Model had some issues and we had to use synchronized blocks instead of lighter volatile fields.