Twitter

Tuesday, December 8, 2009

Java String concatenation Vs StringBuilder (using Dtrace object allocation probe)

"Item 51: Beware the performance of string concatenation" - Effective Java by Joshua Bloch.

Would you like to see how evil String concatenation in java is? continue reading...

Just to avoid these overheads later versions of java introduced StringBuffer(synchronized) and then StringBuilder(unsynchronized) classes.

Never ever use plain string concatenation in any production code. To know why run the following code on your machine...

public class StringSpeed {

public static void main(String[] args) {

try {
Thread.sleep(10000);
}
catch ( InterruptedException e ) {
e.printStackTrace();
}

int N = 100000;

String temp = "";
long start = System.currentTimeMillis();

for ( int i = 0; i < N; i++ ) {
temp = temp + "*";
}

long stop = System.currentTimeMillis();
System.out.println(stop - start);

StringBuilder tempBuilder = new StringBuilder();
start = System.currentTimeMillis();

for ( int i = 0; i < N; i++ ) {
tempBuilder.append("*");
}

stop = System.currentTimeMillis();
System.out.println(stop - start);
}
}
Since the first loop used plain string concatenation it took quite long... whereas the second loop crossed the finish line much quicker. output(on my machine): ======================
13328
8
Isn't the difference worth enough ;) ? The reason for the difference is that the concatenation using "+" has to create so many temp String/StringBuffer objects. To look how many we can use the following dtrace script.
:::object-alloc {
self->str_ptr = (char*) copyin(arg1, arg2+1);
self->str_ptr[arg2] = '\0';
self->classname = (string) self->str_ptr;
@allocs_count[self->classname] = count();
}
Output for first loop (yes!!! 90000+ Strings and 84000+ StringBuilders)
[Ljava/lang/Runnable; 1
java/lang/Shutdown$Lock 1
java/lang/Thread 1
java/security/AccessControlContext 1
[B 3
[[I 3
[S 6
[I 8
java/lang/StringBuilder 84414
java/lang/String 90416
[C 400008
For the second loop it is just...
[Ljava/lang/Runnable; 1
java/lang/Shutdown$Lock 1
java/lang/StringBuilder 1
java/lang/Thread 1
java/security/AccessControlContext 1
[B 2
[[I 2
[S 4
[I 7
java/lang/String 14
[C 62

Thursday, October 29, 2009

Extracting/Unzipping tar.gz file under Solaris

Even though it is a one line command sometimes it is bit hard to remember the syntax...


gzip -dc zippedFile.tar.gz | tar xf -

Friday, September 11, 2009

Opensolaris Virtualbox folder share (mount)




I was trying to share some folders from my windows xp HOST to opensolaris GUEST. But always i got "Operation not applicable to FSType vboxsf".

even after 2 hours of googling i couldn't get the correct answer... And then came my (actually Sun's) mistake to sunlight... because in the virtual box's context help, it is given (look at the image below) that we have to issue "mount -t vboxsf share mount_point" to mount the shared folder.




But it is should NOT be
mount -t vboxsf share mount_point
(Operation not applicable to FSType vboxsf because there is nothing like that but vboxfs)

but it should be
mount -F vboxfs share mount_point
It does make sense vboxfs --> virtualbox filesystem

Atlast happy to have my files accessible in open solaris.

hope someone will land here to get helped.

Saturday, August 29, 2009

Stockholm == cyclist city

Last week I have been there at Stockholm. Nice and green city. Since i am living in Frankfurt for the past 2 years, it was a different experience for me. In Germany (I have lived in 3 to 4 cities in Germany), you cannot see that many cyclists in Stockholm. They really have a broader lane, even in busy routes, just for cyclists.

There were plenty of cyclists in Stockholm. They help to keep the air fresh and themselves active. Just for comparison in Frankfurt the car:cycle ratio would be 500:1 if not 1000:1.

Only after coming back and after doing a little research i came to know that these days European countries are taking effort to cut down emission by encouraging people to use cycles.

BBC News tells you more.

Tuesday, June 2, 2009

Java nio non blocking server & client

Java supports nonblocking io since java 1.4.

But just now i am really using it in one of my projects.

The difference is that the server socket's accept() or a normal socket's read() or write() method need not be blocking (in a single thread) any more.
E.g. with the normal io, if a server is executing the accept() method then it cannot do anything with the previously accepted sockets.

It has changed with nio in the sense that a server can handle (within a single thread)
1. several existing connections and
2. new incoming connections

Let us see an see an example.

The server (Server.java) listens on port 9999 for any incoming connections.
$>javac Server.java
$>java Server

The client (Client.java) sends the text "I am Client : clientXXX" to the server. XXX->is the command line argument; it is just an identifier to distinguish (on the server's console) different clients.
$>javac Client.java
$>java Client 354
$>java Client dfdsfsd

Sample Output:
Sample Output:
serverSocketChannel's registered key is : sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:9999]

Server is listening on: 127.0.0.1:9999
Key ready to perform accept() : sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:9999]
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2633]
I am Client : 354
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2633]
I am Client : 354
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2633]
I am Client : 354
Key ready to perform accept() : sun.nio.ch.ServerSocketChannelImpl[/127.0.0.1:9999]
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2636]
I am Client : dfdsfsd
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2633]
I am Client : 354
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2636]
I am Client : dfdsfsd
Key ready to perform read() : java.nio.channels.SocketChannel[connected local=/127.0.0.1:9999 remote=/127.0.0.1:2633]
I am Client : 354


Server.java






import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Server {

// this is equivalent to the server socket in the non nio world
ServerSocketChannel serverSocketChannel;

// this is the multiplexer which multiplexes the messages received from different clients
Selector selector;

public Server() {
try {

// get a selector
selector = Selector.open();

// get a server socket channel
serverSocketChannel = ServerSocketChannel.open();

// we force the socket to be Non-blocking.
// if it is set to "true" then this socket acts as a normal (blocking) server socket
serverSocketChannel.configureBlocking(false);

// port and ip address where the server listens for connections
InetSocketAddress add = new InetSocketAddress(InetAddress.getLocalHost(), 9999);

// bind the server socket to the ip/port
serverSocketChannel.socket().bind(add);

// register the serverSocketChannel (for incoming connection events) to the selector.
// The "SelectionKey.OP_ACCEPT" parameter tells the selector that this serverSocketChannel registers
// itself for incoming (acceptable) connections
SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("serverSocketChannel's registered key is : " + key.channel().toString());

System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
Server server = new Server();
server.startListening();
}

private void startListening() {

System.out.println("Server is listening on: "
+ serverSocketChannel.socket().getInetAddress().getHostAddress() + ":"
+ serverSocketChannel.socket().getLocalPort());

while (true) {
try {

// this line blocks until some events has occurred in the underlying socket
selector.select();

// get the selected keys set
Set selectedKeys = selector.selectedKeys();

Iterator iterator = selectedKeys.iterator();

while (iterator.hasNext()) {

SelectionKey key = (SelectionKey) iterator.next();

iterator.remove();

// a client has asked for a new connection
if (key.isAcceptable()) {
// only ServerSocketsChannels registered for OP_ACCEPT are excepted to receive an
// "acceptable" key

System.out.println("Key ready to perform accept() : " + key.channel().toString());

// as usual the accept returns the plain socket towards the client
SocketChannel client = serverSocketChannel.accept();

// set the client socket to be non blocking
client.configureBlocking(false);

// register the client socket with the same selector to which we have registered the
// serverSocketChannel
client.register(selector, SelectionKey.OP_READ);
continue;
}

// the client has sent something to be read by this server
if (key.isReadable()) {

System.out.println("Key ready to perform read() : " + key.channel().toString());

// get the underlying socket
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer bb = ByteBuffer.allocate(1024);

// read the msg sent by the client
client.read(bb);

// display the message
bb.flip();
byte[] array = new byte[bb.limit()];
bb.get(array);
System.out.println(new String(array));
continue;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}



Client.java







import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Client {

String myIdentity;

public Client(String pIdentity) {
myIdentity = pIdentity;
}

void talkToServer() {

try {

SocketChannel mySocket = SocketChannel.open();

// non blocking
mySocket.configureBlocking(false);

// connect to a running server
mySocket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 9999));

// get a selector
Selector selector = Selector.open();

// register the client socket with "connect operation" to the selector
mySocket.register(selector, SelectionKey.OP_CONNECT);

// select() blocks until something happens on the underlying socket
while (selector.select() > 0) {

Set keys = selector.selectedKeys();
Iterator it = keys.iterator();

while (it.hasNext()) {

SelectionKey key = it.next();

SocketChannel myChannel = (SocketChannel) key.channel();

it.remove();

if (key.isConnectable()) {
if (myChannel.isConnectionPending()) {
myChannel.finishConnect();
System.out.println("Connection was pending but now is finiehed connecting.");
}

ByteBuffer bb = null;

while (true) {
bb = ByteBuffer.wrap(new String("I am Client : " + myIdentity).getBytes());
myChannel.write(bb);
bb.clear();
synchronized (this) {
wait(3000);
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {

Client client = new Client(args[0]);
client.talkToServer();
}

}