Tuesday, January 19, 2010

Erlang process mailbox performance

I came across this performance issue in Erlang while doing the pattern matching against the mailbox [a.k.a. selective message processing]. Here is the orignal code:


-module (perf).

-export( [start/0] ).

start() ->
S = erlang:now(),
Pids = spawn_n(fun test/1, 10000, []),
wait(Pids),
E = erlang:now(),
io:format( "Total time: ~p~n", [timer:now_diff(E, S)/1000] ).

spawn_n(_F, 0, Acc) -> Acc;
spawn_n(F, N, Acc) ->
Me = self(),
Pid = spawn(fun() -> F(Me) end),
spawn_n(F, N-1, [Pid|Acc]).

test(Pid) -> Pid ! {self(), ok}.

wait([]) -> ok;
wait([Pid|Pids]) ->
receive {Pid, ok} -> ok end,
wait(Pids).


Run time for perf:start() was 1.3 seconds

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.6.5 (abort with ^G)
1> perf:start().
Total time: 1368.038
ok
2>

Now I changed wait(Pids) to wait(lists:reverse(Pids)). After this change, run time for perf:start() was 83 milliseconds.

1> perf:start().
Total time: 83.037
ok

15x improvement just by changing the way mailbox scan is done.

Little things like this are usually overlooked and the language is blamed for the performance issues.

Monday, January 18, 2010

Concurrency in Java - Part 2

In the earlier post I covered the basic cached thread pool.

Another facility offered by Java's concurrency framework is to schedule a thread after certain time or at regular interval (like standard unix cron job). There are 2 ways to schedule the thread at regular interval. First one is to run a task at regular interval regardless of the previous job. Second one is to run a task and wait for the certain interval after the previous job is done.

Second one is helpful in situation like crawlers. It is necessary to download the pages with some politeness factor [wait for sometime before downloading a page from the same website].


ScheduledExecutorService executionService = Executors.newScheduledThreadPool(2);


Above code snippet create a pool of 2 threads. This service can schedule the threads at regular interval.

ScheduledExecutorService provide a method schedule

Runnable task = new Runnable() {
public void run() {
System.out.println( "I am responsible for downloading a page" );
return;
}
};
/* TimeUnit is defined within java.util.concurrent package */
Future future = executionService.schedule(task, 2000, TimeUnit.MILLISECONDS);


The above code schedule a task to run after 2 seconds [2000 milliseconds]. schedule method return a future object. This future object can be used to check the status of the task [isDone method] or to cancel the task [cancel method]. Read more about the future object and the methods available here.

ScheduledExecutorService also support repeated execution of a task via scheduleAtFixedRate and scheduleWithFixedDelay.

scheduleAtFixedRate method schedule the task at regular interval. This method does not check if the previously scheduled task is finshed or not.

scheduleWithFixedDelay method is similar to scheduleAtFixedRate except that this method wait for the previous execution to finish, wait for the fixed interval and then schedule the task again.

Sunday, January 17, 2010

Concurrency in Java

Java 5.x introduced the concurrency framework. It make the life of developer easier to run multiple threads. This framework also take care of thread caching this reducing the number of spawned threads in the system.

When the concepts of thread was introduced in the operating systems, it was considered light-weight processes. As the clock speed of the CPU is increasing dramatically and also number of CPU cores available for the programs are increasing, even this light-weight processes are deemed to costly to start. Thus introduced the concept of cached threads. Erlang solve this problem by introducing ultra-light-weight processes. Millions of such processes can be spawned within few seconds. This is not the case in kernel threads. Even when kernel threads are used, there is a cost of context switching to schedule those threads from wait state to run state.

I am new to Java concurrency framework. So I am taking baby steps to learn to use the classes available in Java 5.x. All the concurrency related classes are in java.util.concurrent package.

First step in start using these classes is to introduce Executors class. This class has several class methods to create thread pools.


import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

ExecutorService threadPool = Executors.newCachedThreadPool();


The above code create a cached thread pool. Behavior of this thread pool is documented here.

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors


A task can be submitted to the newly created thread pool for execution. A task must be an instance of Runnable interface. Submitting a task to the ExecutorService will return an instance of Future interface. This is a wrapper around the task submitted. This instance can be used to query the submitted task for completion, as well as to cancel the task.



Future task = threadPool.submit( new Runnable() {
public void run() {
System.out.println( "Hello world from within the thread pool" );
}
});


Finally wait for the task to be completed


while ( !task.isDone() ) {
}


Once the task is completed and thread pool is no-longer necessary, send shutdown message to the thread pool to terminate all the threads created.


threadPool.shutdown();
while (!thread.isTerminated()) {
}


There it is. First Hello world code using the Concurrent Thread Pool in Java. As and when I learn new methods in this framework, I will write about that here.



Until then, happy thread pooling and utilizing all the cores on the system.

Update: Download the source from here

Thursday, October 8, 2009

What do you mean by giving more than 100%?

Here is a little something someone sent me that is _indisputable_ mathematical logic. (It also made me Laugh Out Loud.)

Remember, this is a strictly mathematical viewpoint. It goes like this:

What Makes 100%? What does it mean to give MORE than 100%? Ever wonder about those people who say they are giving more than 100%? We have all been to those meetings where someone wants you to give over 100%. How about achieving 103%? What makes up 100% in life?

Here's a little mathematical formula that might help you answer these questions:

If:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

is represented as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26.

Then:

H-A-R-D-W-O-R-K
8+1+18+4+23+15+18+11 = 98%*


and


K-N-O-W-L-E-D-G-E
11+14+15+23+12+5+4+7+5= 96%

But,*

A-T-T-I-T-U-D-E
1+20+20+9+20+21+4+5 = 100%

And,

B-U-L-L-S-H-I-T
2+21+12+12+19+8+9+20 = 103%

AND, look how far ass kissing will take you.

A-S-S-K-I-S-S-I-N-G
1+19+19+11+9+19+19+9+14+7 = 118%
So, one can conclude with _mathematical certainty_, that while* Hardwork* and *Knowledge *will get you close, and* Attitude *will get you there, its the *Bullshit* and *Ass kissing* that will put you over the top.

Tuesday, September 29, 2009

How to see the running processes in erlang shell

Erlang provides a built-in utility called etop, that is same as standard top utility on Unix. Instead of monitoring processes on the operating system, etop show the current running/active Erlang processes. By default it starts a GUI window to show the processes running. Sometimes GUI is not desirable especially when the Erlang shell is running on production servers. Documentation does not show any way to start etop in text mode. Here is how to run it


etop:start([{output, text}]).

Detecting rejected file upload in PHP code

PHP can be configured to reject the file uploads exceeding some limit via upload_max_filesize server configuration parameter (in php.ini). As per the documentation here, even though the file upload is rejected, an entry is made in $_FILES array with error code set to UPLOAD_ERR_INI_SIZE. This is documented here.

Practically speaking this is not the case. When the uploaded content size exceed upload_max_filesize, $_FILES array is empty. This array cannot be inspected to find the reason for the error. I found a hack to do this.

* For file uploads, $_SERVER['CONTENT_TYPE'] is always set to multipart/form-data followed by the multipart boundary string.
* $_SERVER['CONTENT_LENGTH'] will be set to the content-length in the http header.

Combination of above 2 can be used to detect the file upload exceeding upload_max_filesize.

if ( stripos( $_SERVER['CONTENT_TYPE'], 'multipart/form-data') === 0 && intval($_SERVER['CONTENT_LENGTH']) > 0 &&
count($_FILES) == 0) {
error_log( 'File upload rejected due to file size exceeding upload_max_filesize limit' );
}

Saturday, September 26, 2009

Load balancing in Erlang using pg2 process groups

While working with some project @ my current workplace, we came across a situation where we are using pg2 process group. Apparently pg2 does not load balance across processes registered in the pg2 group. It usually done in round robin way. So it may happen that even though many processes are registered under same group, but all messages will get queues in single process.

My co-worker and I came with an algorithm to solve this. It is describe here.

Book Promotion