Tuesday, July 24, 2012

How to send an email with attachment from command line in unix?


How to send the email with attachment from command line?


This is useful when one is working remotely and does not have access to any mailing programs other than command line.
Install following programs on Ubuntu as followed
sudo apt-get install mailx sendmail
sudo apt-get install sharutils

We can use following command to actually send the email. 

 [user@machine~]$ uuencode FileWithExtention FileWithExtention | mailx -s 'Subject' user_name@domain

This page provides more information.

Monday, July 23, 2012

String Concatenation Performance

Title:

Find string concatenation performance using different ways of string concatenation.

Experiment details

Following are the details of the environment.
  •  Operating System: Linux version 2.6.28-19-generic
  •  Processor
    •  model name   : Intel(R) Xeon(R) CPU            5140  @ 2.33GHz
    •  stepping         : 6
    •  cpu MHz        : 2327.593
    •  cache size       : 4096 KB
  •  JVM
    •  java version : "1.6.0_13"
  •  Memory:
    •  MemTotal:  3094916 kB

Method

  1.  Create an array of 5000/ 10000 String objects.
  2.  Calculate the start time before staring the concatenation operation.
  3.  Write a loop to concatenate all these objects using various ways (.concat method of String class, using StringBuffer, using StringBuilder, using + operator)
  4.  Calculate the end time after concatenation operation.
  5.  A Java program that was used to calculate the metrics is at the end of this document.

Terminology

Iterations - Number of times the process of concatenation is performed during the execution of the program.
Operations - Number of concatenation operations done (5000/10000).

Observations

Following charts provide data for two different set of experiment.
  1.  Multiple iterations - 10, 100, 1000 iterations
  2.  Multiple operations  - 5000/ 10000 operations

Here are the graphs that show the performance of each of the concatenation operation.




  1. It is observed that wrong usage of StringBuilder requires largest time to perform operation.
  2. Using + sign to concatenate performs second worst.
  3. Using String.concat() method performs relatively better than using + sign.
  4. Contradictory to traditional belief the usage of StringBuffer does not cause any issues. It performs as well as using StringBuilder.
  5. It is important to understand that StringBuilder should be used in one shot. One call to StringBuilder.append() method is the right way to concatenate strings.

Conclusion

  1.  StringBuilder and StringBuffer perform in the same way when used in the right fashion.
  2.  Wrong usage of StringBuilder can cause severe performance penalties.

Tip

  1. StringBuilder should be used when only one thread is going to perform concatenation operation. 
  2. StringBuffer should be used when multiple threads are going to perform concatenation operation.

Further Experiments

* Calculate memory usage while performing the same experiments.

Ref:


* StringBuffer

Program


Here is the program that I used to get above metrics. One needs to provide different arguments to this program while running to have different iterations. One can update the value of variable limit to change the number of operations. In this program, currently the limit is set to 5000.

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;


/**
 * 


 * @author Shilpa Deshpande
 * 


 */
public class StringConcatenationPerformanceMeasurer {

    private final int iteration;
    private final String fileName;

    class Measurement{
        private long concat, plus, wrongBuilder, rightBuilder, stringBuffer;
    
        
        /**
         * @return The concat
         */
        public long getConcat() {
        
            return concat;
        }
    
        
        /**
         * @param concat The concat to set
         */
        public void setConcat(long concat) {
        
            this.concat = concat;
        }
    
        
        /**
         * @return The plus
         */
        public long getPlus() {
        
            return plus;
        }
    
        
        /**
         * @param plus The plus to set
         */
        public void setPlus(long plus) {
        
            this.plus = plus;
        }
    
        
        /**
         * @return The wrongBuilder
         */
        public long getWrongBuilder() {
        
            return wrongBuilder;
        }
    
        
        /**
         * @param wrongBuilder The wrongBuilder to set
         */
        public void setWrongBuilder(long wrongBuilder) {
        
            this.wrongBuilder = wrongBuilder;
        }
    
        
        /**
         * @return The rightBuilder
         */
        public long getRightBuilder() {
        
            return rightBuilder;
        }
    
        
        /**
         * @param rightBuilder The rightBuilder to set
         */
        public void setRightBuilder(long rightBuilder) {
        
            this.rightBuilder = rightBuilder;
        }
    
        
        /**
         * @return The stringBuffer
         */
        public long getStringBuffer() {
        
            return stringBuffer;
        }
    
        
        /**
         * @param stringBuffer The stringBuffer to set
         */
        public void setStringBuffer(long stringBuffer) {
        
            this.stringBuffer = stringBuffer;
        }
    }

    /**
     * @param fileName 
     * @param iteration 
     * 
     */
    public StringConcatenationPerformanceMeasurer(int iteration, String fileName) {
        this.iteration = iteration;
        this.fileName = fileName;

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        int iteration = 10;
        String fileName = "StringConcatenationMeasurement.xls";
        try {
            System.out.println("Please enter number of iterations.");
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            String readLine = in.readLine();
            iteration = Integer.valueOf(readLine);          
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        StringConcatenationPerformanceMeasurer instance = new StringConcatenationPerformanceMeasurer(
                iteration, fileName); 
        try {
            instance.checkStringConcatenationPerformance();
            
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @throws Exception 
     * 
     */
    public void checkStringConcatenationPerformance() throws Exception {
            
        ArrayList measurementList = new ArrayList();
        for (int k = 0; k < iteration; k++) {
            int limit = 5000;
            String[] array = new String[limit];
            for (int i = 0; i < limit; i++) {
                array[i] = "e" + i + " ";
            }
            // Native String Concatenation using concat method
            long t0 = System.currentTimeMillis();
            String sbS = "";
            for (int i = 0; i < limit; i++) {
                sbS = sbS.concat(array[i]);
            }
            long t1 = System.currentTimeMillis();
            //System.out.println("Final String using concat " + sbS);
            sbS = null;
            
            
            // Wrong String concatenation using StringBuilder
            StringBuilder sb = new StringBuilder();
            sbS = "";
            for (int i = 0; i < limit; i++) {
                sbS = (sb.append(sbS).append(array[i])).toString();
                sb = new StringBuilder();
            }
            long t2 = System.currentTimeMillis();
            //System.out.println("Final String - wrong usage of StringBuilder " + sbS);
            sbS = null;
            
            
            // Right String concatenation using StringBuilder
            sb = new StringBuilder();
            for (int i = 0; i < limit; i++) {
                sb.append(array[i]);
            }
            sbS = sb.toString();
            //System.out.println("Final String - right usage of StringBuilder " + sbS);
            long t3 = System.currentTimeMillis();
            sbS = null;
            
            
            // String concatenation using +
            sbS = "";
            for (int i = 0; i < limit; i++) {
                sbS = sbS + array[i];
            }
            long t4 = System.currentTimeMillis();
            //System.out.println("Final String using + " + sbS);
            sbS = null;
            
            
            // String concatenation using StringBuffer
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < limit; i++) {
                buffer.append(array[i]);
            }
            sbS = buffer.toString();
            //System.out.println("Final String using StringBuffer " + sbS);
            long t5 = System.currentTimeMillis();
            sbS = null;
            
            
            System.out.println("=================================");
            System.out.println("Native String Concatenation using concat method (Time in Milliseconds) " + (t1 - t0));
            System.out.println("Wrong String concatenation using StringBuilder (Time in Milliseconds) " + (t2 - t1));
            System.out.println("Right String concatenation using StringBuilder (Time in Milliseconds) " + (t3 - t2));
            System.out.println("String concatenation using + (Time in Milliseconds) " + (t4 - t3));
            System.out.println("String concatenation using StringBuffer (Time in Milliseconds) " + (t5 - t4));
            System.out.println("=================================");
            
            Measurement mm = new Measurement();
            mm.setConcat((t1-t0));
            mm.setWrongBuilder((t2-t1));
            mm.setRightBuilder((t3-t2));
            mm.setPlus((t4-t3));
            mm.setStringBuffer((t5-t4));
            measurementList.add(mm);
            
        }      
    }    
}


.

Wednesday, March 30, 2011

HttpFox

A few months ago, I worked on a project where the request originating on browser was to be transferred to a whole different server farm. The project involved Apache webserver, GWT, Tomcat servers, of course some configuration in each of these layers. The Firefox Extention that really helped me was - HttpFox. This extension allows us to see the originating request. In the case of GWT, one can see the request type, its parameters. We can observe the response from the server. Sometimes just the response code is more helpful than any logs on the server side. One can see the URL that we are hitting. In our case, it was crucial to construct right URL so that we know we reach to the right farm of servers.


I used the same extension two months ago when I had to reverse engineer a working URL. I needed to find how the URL is generated and what does it translate to. This extension was really really helpful. I had finished debugging in 15 minutes from the time I started. If you are using Firefox 3.6 and cannot download this extension using firefox, try downloading it manually. It worked for me.

Next time you have to develop/reverse engineer anything that deals with URL's, fire up this one. Good luck!

Tuesday, June 8, 2010

GWT Canvas

In my recent adventure about using GWT canvas to draw some images at work lead me to one discovery. Lets assume that we are trying to draw a polygon, so we will use following code

canvas = new GWTCanvas(500,500);
canvas.setFillStyle(color);
canvas.beginPath();
canvas.moveTo(100, 500);
canvas.lineTo(150, 400);
canvas.moveTo(150, 400);
canvas.lineTo(450, 400);
canvas.moveTo(450, 400);
canvas.lineTo(500, 500);
canvas.moveTo(500, 500);
canvas.lineTo(100, 500);
canvas.closePath();
canvas.stroke();
canvas.fill();


This will draw the polygon but will not fill it with the Color that we have set as fill style. If one comments out the lines corresponding to moveTo() method, the fill() method works and fills the polygon with the color that we have specified.

Wanted to share.
Cheers!!

Friday, March 19, 2010

SQLException: Protocol violation - A possible solution

Sometime ago at work I encountered an exception while inserting a row in a table.
We kept seeing following exception
when we were trying to insert a new row in a table using jdbc (using ojdbc14.jar and oracle 9 as database). DBA tried creating the table
again, she could run the query well in sqlplus, golden.

java.sql.SQLException: Protocol violation at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java: 146) at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java: 208) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:764) at
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:955)
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1168)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285)
oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3390)
com.myCompany.myPackage.MyDao.insert(MyDAO.java:122)

The table in which we were trying to do an insert looked as followed

FIELD | TYPE | CONSTRAINT | ADDITIONAL CONSTRAINT |
PERSON_ID | NUMBER| PRIMARY KEY |SEQUENCE GENERATED ID |
CREATED_ON | DATE | NOT NULL |
STATUS| VARCHAR (1)| NOT NULL | THE VALUES ARE EITHER 'A' OR 'I'|
LAST_NAME| VARCHAR (100)| NOT NULL | |

The query was something like following

INSERT INTO PERSON (LAST_NAME,STATUS) VALUES (?,'A');

When we replaced query following query, it worked smooth.

INSERT INTO PERSON (NAME,STATUS) VALUES (?,?);

Apparently we cannot insert into table when there is an static value in
the statement using jdbc. This solution was not found in any google search at that time,
may be this blog post will help anybody who encounters it :)

Note: The queries and table in this blog are changed so as to protect the intellectual property.

Wednesday, February 3, 2010

Snow Leopard, Safari 4.0.4 and GWT

If you encounter this issue (http://code.google.com/p/google-web-toolkit/issues/detail?id=4220) about running your gwt app on snow leopard with safari 4.0.4, try this solution (http://grack.com/blog/2009/11/16/fix-for-gwt-hosted-mode-crash-with-safari-4-0-4/). It works. I spent few hours finding it, so thought would share.

Friday, January 1, 2010

10 Most populart programming articles in 2009

I found this list here

I will also enumerate the articles which I loved in 2009, in few days!

Happy New Year to everyone...