<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8330281815778885186</id><updated>2024-10-24T03:33:26.797-07:00</updated><category term="Java 7 Fork Join"/><category term="jdbclogger prepared statements jdbc"/><category term="ssh-tunneling reverse-tunneling ssh reverse tunneling"/><title type='text'>Moon of my life</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://moonofsaikatslife.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://moonofsaikatslife.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kazi Abdullah Saikat</name><uri>http://www.blogger.com/profile/16836753853458093531</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8330281815778885186.post-279945261209619461</id><published>2012-04-16T13:36:00.000-07:00</published><updated>2012-04-16T13:44:38.540-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jdbclogger prepared statements jdbc"/><title type='text'>Finding your SQL statements run on the database through JDBC</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;i&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small; font-weight: normal;&quot;&gt;Note: The article was written back in 2009. I recommend&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://code.google.com/p/log4jdbc/&quot; style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: medium; font-weight: normal;&quot; target=&quot;_blank&quot;&gt;log4jdbc&lt;/a&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small; font-weight: normal;&quot;&gt;&amp;nbsp;instead of jdbclogger now a days.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;i&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small; font-weight: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;h2&gt;


&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;Why is it of any interest at all?&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;The application may not log all the SQL statements it is executing. If you are using frameworks/tools that generate SQL statements, then it can be very handy to find out what the generated statements look like (specially if you looking forward to optimize you database performance using indexes and such).&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Of-course, a lot of the frameworks (such as Hibernate, iBatis) out there do allow you to configure their logging so that you can see what SQLs are being generated. However for &lt;i&gt;&lt;span style=&quot;color: #3d85c6;&quot;&gt;prepared statements&lt;/span&gt;&lt;/i&gt;, most of them fail to display the final SQL executed on your database.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;


&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;Tools:&lt;/span&gt;&lt;/h2&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;One interesting tool to get this job done is: &lt;a href=&quot;http://jdbclogger.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;JDBC Logger&lt;/a&gt;. Its easy to configure specially if you are already using a connection pool.
&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;


&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;Configuration:&lt;/span&gt;&lt;/h2&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Follow the steps below to configure your connection pool (Tomcat 6.0) to use JDBC Logger:
&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;download the binaries and put the jar files in your classpath&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;configure jdbc to use JDBC Logger&#39;s driver
&lt;/span&gt;&lt;div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&amp;lt;Resource
      name=&quot;jdbc/mydb&quot;
      auth=&quot;Container&quot;
      type=&quot;javax.sql.DataSource&quot;
      ...
      driverClassName=&quot;&lt;b&gt;net.sourceforge.jdbclogger.JdbcLoggerDriver&lt;/b&gt;&quot;
      url=&quot;&lt;b&gt;jdbc:oracle:thin:@localhost:1521:orcl&lt;/b&gt;&quot;
   /&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;create&amp;nbsp;
&lt;strong&gt;jdbclogger.properties&lt;/strong&gt;&amp;nbsp;in your application server classpath (on Tomcat 6, you can add it to your &lt;i&gt;$CATALINA_HOME/lib&lt;/i&gt; directory)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;add your desired jdbc driver configuration into the file created above. Example entry: &lt;strong&gt;jdbclogger.driver=oracle.jdbc.driver.OracleDriver&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;set logging level for JDBC Logger to DEBUG: &lt;strong&gt;log4j.logger.net.sourceforge.jdbclogger=DEBUG&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Done.

Note that, the amount of SQL statements logged may be a bit too much to have in one log file. In that case, you can configure log4j to let JDBC Logger to log the SQL statements into a separate file.
&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://moonofsaikatslife.blogspot.com/feeds/279945261209619461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://moonofsaikatslife.blogspot.com/2012/04/finding-your-sql-statements-run-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/279945261209619461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/279945261209619461'/><link rel='alternate' type='text/html' href='http://moonofsaikatslife.blogspot.com/2012/04/finding-your-sql-statements-run-on.html' title='Finding your SQL statements run on the database through JDBC'/><author><name>Kazi Abdullah Saikat</name><uri>http://www.blogger.com/profile/16836753853458093531</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8330281815778885186.post-5446627258266048601</id><published>2012-04-16T13:27:00.000-07:00</published><updated>2012-04-16T13:36:37.982-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ssh-tunneling reverse-tunneling ssh reverse tunneling"/><title type='text'>SSH Tunneling &amp; Reverse Tunneling</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;

&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;SSH Tunneling:&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;In short, SSH tunneling allows unix users to connect to a remote computer (through ssh) and map a local port to the remote computer port.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;

&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;SSH Reverse Tunneling:&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;SSH reverse tunneling allows a unix user to connect to a remote computer and map a port on the remote computer to a port in the local machine.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;

&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;The Problem:&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;i&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;We need to test some kind of external service which redirects back to one of our provided service urls. We need a server with a public IP to do it. However, its a pain to always compile, deploy on the public server and test.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;i&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Instead, it will be much easier to be able to map a remote server port to a port on my local machine so that I can deploy my services locally to which the external service will redirect to.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Assume, our external server hostname is mapped to: example.com and we will use sso.example.com to provide Single Sign On (sso) support. From the example site, when the user wants to log in using the SSO service provided by sso.example.com, the user gets redirected to sso.example.com with certain request parameters. Once the user has successfully logged into sso.example.com, he gets redirected back to example.com with some parameters which indicate that the user logged in successfully.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Now to test this, we need to re-deploy the services on to example.com every time we fix something. Of-course, we can mount a file system on the public server that reads the deployment files from a nfs share which can be mounted to some directory on your machine.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;But if the public server and your machine are in different networks and your machine do not have a public IP, then its slightly more tricky to achieve. SSH reverse tunneling will help us come to a solution.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Assume that your machine host name is &quot;developer&quot; (it can of-course be an IP).&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;strong&gt;&lt;em&gt;&lt;span style=&quot;color: #cc0000; font-family: Arial, Helvetica, sans-serif;&quot;&gt;ssh -f user@example.com -R example.com:8081:developer:8080 -N&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;What this will do is it will log into the remote server &quot;example.com&quot;, open a port &quot;8081&quot; and connect it to &quot;developer:8080&quot;. So, when anyone logs into &quot;example.com&quot; and sends a request to &quot;http://localhost:8081&quot;, the request comes to port 8080 on developer.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;But this is no fun since to make the request, a user has to log into example.com. So to fix that, we can map another port on example.com to forward everything to port &quot;8081&quot; which is the reverse tunneling port. To do it, we have to first log into example.com and execute the following command:&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;em&gt;&lt;strong&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;em&gt;&lt;strong&gt;&lt;span style=&quot;color: #cc0000; font-family: Arial, Helvetica, sans-serif;&quot;&gt;ssh -f user@example.com -L example.com:8080:localhost:8081 -N&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;em&gt;&lt;strong&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Once this command is executed, all requests send to example.com:8080 will be forwarded to example.com:8081 which in turn will forward everything to&amp;nbsp; &quot;developer:8080&quot;.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;

&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;Why not try this shortcut?&lt;/span&gt;&lt;/h2&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;color: #cc0000; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;em&gt;&lt;strong&gt;ssh -f user@example.com -R example.com:8080:developer:8080 -N&lt;/strong&gt;&lt;/em&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;This does log into example.com and map port 8080 to forward everything to developer:8080.
However, it only works if someone logs into example.com and sends a request to &quot;localhost:8080&quot;.
It doesn&#39;t work if a user simply sends the request to &quot;example.com:8080&quot;.
The only way to make the shortcut mentioned above work is to configure the ssh daemon with the &lt;em&gt;GatewayPorts&lt;/em&gt; option enabled.
By default, sshd binds the reverse tunneling port to the loop back interface only,
thus preventing remote hosts from using the reverse tunneling port.
The default value for &lt;em&gt;GatewayPorts&lt;/em&gt; is &lt;em&gt;no&lt;/em&gt; .&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://moonofsaikatslife.blogspot.com/feeds/5446627258266048601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://moonofsaikatslife.blogspot.com/2012/04/ssh-tunneling-reverse-tunneling.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/5446627258266048601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/5446627258266048601'/><link rel='alternate' type='text/html' href='http://moonofsaikatslife.blogspot.com/2012/04/ssh-tunneling-reverse-tunneling.html' title='SSH Tunneling &amp; Reverse Tunneling'/><author><name>Kazi Abdullah Saikat</name><uri>http://www.blogger.com/profile/16836753853458093531</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8330281815778885186.post-2353698871031030397</id><published>2011-08-17T02:26:00.000-07:00</published><updated>2011-08-17T11:36:49.657-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java 7 Fork Join"/><title type='text'>How Java 7 Fork/Join can improve performance</title><content type='html'>Like many Java developers out there, I am also playing with the new Java 7 features. One of the features that caught my attention is the new Fork/Join framework.&lt;div&gt;&lt;br /&gt;&lt;div&gt;I will not waste a lot time explaining how to use Fork/Join in a program since that is already covered well at: &lt;a href=&quot;http://download.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html&quot;&gt;Fork/Join tutorial&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, this is what I did to test it out.&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Disclaimer: &lt;i&gt;Java&#39;s time calculation is surely debatable and there are quite a few talks out there that criticize micro bench marking as well. So please keep that in mind before expecting the results to be accurate in a production system.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;First the (imaginary) problem&lt;hr /&gt;&lt;/div&gt;&lt;div&gt;Assumptions:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Add operation is expensive&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Problem:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Input: the program is given an array of numbers&lt;/li&gt;&lt;li&gt;Output: the program must compute the summation of the given numbers&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;The program first iterates over an array of &lt;i&gt;SlowNumber&lt;/i&gt; objects and calculates the sum of it. The time needed to perform this operation is what is later in the post referred to as &lt;i&gt;Serial Execution Time&lt;/i&gt;. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After that, the program:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Breaks down the array of &lt;i&gt;SlowNumber&lt;/i&gt; objects into smaller arrays with start and end indexes&lt;/li&gt;&lt;li&gt;Passes these smaller segments into separate forks&lt;/li&gt;&lt;li&gt;Keeps a small segment for itself to calculate the sum&lt;/li&gt;&lt;li&gt;Gets the sums calculated by the child-tasks and adds them together with the sum found in the previous step&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;This time needed by the whole process of calculating the sum in parallel is referred to as &lt;i&gt;Parallel Execution Time&lt;/i&gt; later in the post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have created a &lt;em&gt;SlowNumber&lt;/em&gt; class that allows us to add another &lt;i&gt;SlowNumber&lt;/i&gt; to it. Every add operation sleeps for a certain amount of time simulating a time consuming operation.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;private class SlowNumber {&lt;br /&gt;private Long value = 0L;&lt;br /&gt;//&lt;br /&gt;public void add(final SlowNumber number) {&lt;br /&gt;sleep(TIME_PER_OPERATION_IN_MILLIS);&lt;br /&gt;value += number.value;&lt;br /&gt;}&lt;br /&gt;// rest of the class&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Now the interesting part. We have a &lt;em&gt;SlowAdd&lt;/em&gt; task that extends &lt;em&gt;RecursiveTask&amp;lt;slownumber&amp;gt;&lt;/em&gt;. The &lt;em&gt;compute&lt;/em&gt; method checks if the given number of &lt;em&gt;SlowNumber&lt;/em&gt; objects are more than a certain size. If so, it simply forks more &lt;em&gt;SlowAdd&lt;/em&gt; tasks and divides the array of &lt;em&gt;SlowNumber&lt;/em&gt; objects into smaller parts keeping the last set of numbers for itself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is how the first part of the compute method in &lt;em&gt;SlowAdd&lt;/em&gt; looks like:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;class SlowAdd extends RecursiveTask&lt;slownumber&gt; {&lt;br /&gt;//...&lt;br /&gt;@Override&lt;br /&gt;protected SlowNumber compute() {&lt;br /&gt;List&amp;lt;ForkJoinTask&amp;lt;SlowNumber&amp;gt;&amp;gt; childAddTasks = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;// start from fromIndex&lt;br /&gt;int computeBeginning = fromIndex;&lt;br /&gt;// if more numbers than NUMBERS_PER_FORK&lt;br /&gt;if (toIndex - fromIndex &amp;gt; NUMBERS_PER_FORK) {&lt;br /&gt;// create forks with own fromIndex and toIndex to perform add operation&lt;br /&gt;for (int i = fromIndex; i &amp;lt; toIndex; i += NUMBERS_PER_FORK) {&lt;br /&gt;if (i + NUMBERS_PER_FORK &amp;gt;= toIndex) {&lt;br /&gt;// ok, have less or equal to NUMBERS_PER_FORK number of items, so don&#39;t fork&lt;br /&gt;computeBeginning = i;&lt;br /&gt;break;&lt;br /&gt;}&lt;br /&gt;SlowAdd slowAdd = new SlowAdd(numbers, i, i + NUMBERS_PER_FORK);&lt;br /&gt;childAddTasks.add(slowAdd);&lt;br /&gt;slowAdd.fork();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;// ...&lt;/slownumber&gt;&lt;/pre&gt;&lt;/div&gt;Once the child tasks are created, the task continues to perform summation on its own share of numbers. After that, it tries to add the summations calculated by the child tasks with its own summation to calculate the total.&lt;div&gt;&lt;pre&gt;      // now perform addition on own share of numbers&lt;br /&gt;SlowNumber total = new SlowNumber();&lt;br /&gt;for (int i = computeBeginning; i &amp;lt; toIndex; i++) {&lt;br /&gt;total.add(numbers[i]);&lt;br /&gt;}&lt;br /&gt;if (!childAddTasks.isEmpty()) {&lt;br /&gt;for (ForkJoinTask&lt;slownumber&gt; childAddTask : childAddTasks) {&lt;br /&gt;// add results created by children&lt;br /&gt;total.add(childAddTask.join());&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;return total;&lt;br /&gt;}&lt;br /&gt;// ...&lt;br /&gt;}&lt;/slownumber&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Now to execute the &lt;em&gt;SlowAdd&lt;/em&gt; task, all we need to do is:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;SlowAdd slowAdd = new SlowAdd(slowNumbers, 0, slowNumbers.length);&lt;br /&gt;ForkJoinPool addTaskPool = new ForkJoinPool(i + 1);&lt;br /&gt;final SlowNumber parallelValue = addTaskPool.invoke(slowAdd);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;After running the example code quite a few times on a HP EliteBook 8540w running Ubuntu 11.04, the program outputs something very similar to what follows:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;Expected total: 164, took: 333 ms&lt;br /&gt;Found slowAdd total: 164, number of CPU: 1, took: 348 ms&lt;br /&gt;Speed up by: 95.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 2, took: 313 ms&lt;br /&gt;Speed up by: 106.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 3, took: 172 ms&lt;br /&gt;Speed up by: 193.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 4, took: 132 ms&lt;br /&gt;Speed up by: 252.0%&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Note that, the delay per &lt;em&gt;add&lt;/em&gt; operation is set to 10ms. Reducing the delay to only 1ms results into something as follows:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;Expected total: 164, took: 36 ms&lt;br /&gt;Found slowAdd total: 164, number of CPU: 1, took: 42 ms&lt;br /&gt;Speed up by: 85.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 2, took: 34 ms&lt;br /&gt;Speed up by: 105.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 3, took: 19 ms&lt;br /&gt;Speed up by: 189.0%&lt;br /&gt;Found slowAdd total: 164, number of CPU: 4, took: 15 ms&lt;br /&gt;Speed up by: 240.0%&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Still a &lt;b&gt;240%&lt;/b&gt; performance improvement despite the overload of breaking the input into smaller pieces, creating new tasks and switching of tasks by the task-manager.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a chart I made for a visual understanding of the difference:&lt;/div&gt;&lt;br /&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 816px; height: 1056px;&quot; src=&quot;https://github.com/saikat047/My-JDK-7-fun-project/raw/master/images/fork-join.png&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;div&gt;Thought, this micro benchmark looks straight forward enough to motivate all of us to convert all our existing code to use Fork/Join, it should be noted that the problem I chose to demonstrate here is straight forward enough to be broken down into smaller problems which can be executed independently in parallel.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you think about the popular Map/Reduce problem, then the mapping part can definitely be performed in parallel using fork/join approach to speed up the performance. However, if a set of tasks are interdependent and depends on each others results, then the outcome will surely be different.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the worst case, if a set of tasks are dependent in a way that results in a linear dependency graph i.e. A -&amp;gt; B -&amp;gt; C -&amp;gt; D, then no matter how many CPUs are available, the tasks will always be executed serially. In such cases, Fork/Join can even decrease the performance of the application since the tasks will be executed serially but with the overhead of the task scheduler.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first two columns in every bar-chart proves that when the parallel execution has only one CPU, it actually decreases the performance a little. The benefit of parallel execution is only visible when there are more than one CPU.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can download the full source code &lt;a href=&quot;https://raw.github.com/saikat047/My-JDK-7-fun-project/master/src/test/ForkJoinTest.java&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;Feel free to share your opinion.&lt;/div&gt;&lt;meta equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://moonofsaikatslife.blogspot.com/feeds/2353698871031030397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://moonofsaikatslife.blogspot.com/2011/08/how-java-7-forkjoin-can-improve.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/2353698871031030397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8330281815778885186/posts/default/2353698871031030397'/><link rel='alternate' type='text/html' href='http://moonofsaikatslife.blogspot.com/2011/08/how-java-7-forkjoin-can-improve.html' title='How Java 7 Fork/Join can improve performance'/><author><name>Kazi Abdullah Saikat</name><uri>http://www.blogger.com/profile/16836753853458093531</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>