Difference between Debug build and Release build

Cool, after days and days of debugging, I’m ready to release my work!

Yeah nice, but what if your ‘release build’ crashes? Well read on, to see what might have changed.

Before knowing the differences between Debug and Release build, you should know that they are really different. I learned it the hard way. Just today, I wanted to show someone my half cooked software, so I quickly told my Visual Studio 2010 to make a release build for a demo. And I was really going to upload it on sourceforge, for anyone and everyone to download. Sweet, my system hanged.

Imagine what would have happened had it not crashed on my system (crashes are random, at the worst they don’t happen during testing), but on users computer. Uh oh, disaster.

So lets see what changes when you change from Debug configuration of build to Release build.

ImageAlso note that, there can be many more configurations, like “Debug DLL”, “Universal Release” etc. Its just how you configure it, and what name you give to your configuration.

1. Optimization

This is the main reason you package your final software with “Release” build. While debugging there are debugging symbols, extra lines of code, and the IDE’s book keeping attached with your software. So naturally your debug build is slower and heavier by several orders. For instance my debug executable was 6.15 MB while release executable is only 2.74 MB. See how it has doubled.
In fact there is an option in IDE to turn off optimization, as optimization by compiler, modifies code in unpredictable manner, something which can make debugging hard or even impossible.

Debug configuration has Optimization turned off

2. The protective cover is gone

If you are facing the trouble, “software crashes in release, while in debug it was running fine”, your trouble spot is most probably this one.
In debug mode, the compiler is gentle on you and provides a protection against your um.. erroneous code, by

  • allocating extra memory before and after, each block of storage. And this extra space is initialized with values like 0 for integers. Thus your attempts to access beyond array size won’t let you corrupt some other data structure.
  • it also initializes variables to some safe value. Like the pointers are initialized with NULL value, or some ridiculous value that will cause segfault, if you try to access it. Thus the problem of wild pointers would not appear in debug, but cause troubles in release build.

So if your release build is crashing, you should first check for out of bound access and uninitialized variables.

3. Use Release Library for Release build and Debug Library for Debug build

Well, this is where I faulted. I was using debug library, of framework my program was dependent upon for Linking. While configuring project settings, I made these settings default, and thus they were used for both Debug and Release build. As long as I was debugging, everything went fine, but my release build, well crashed…

Most third party libraries support different builds, like Release or Debug, Static or Dynamic and so on. So while, you are developing code, and will be debugging actively, it is appropriate to have debug libraries linked to your project. This will aid debugging as, the library will provide much more detailed messages for warnings and errors.
But in case of release, only use Release version of library for linking. Release build of libraries are optimized, and fail silently in case of error (you don’t want to show your users a scary message, right?!).

4. Test your program on various systems

Another major difference in debug and release, is that while debug build was playing in small backyard (your computer), the release build will be playing in open fields (users computer, or even smartphones, tablets etc.). You spend extra time, configuring your environment to ensure, your program runs. But on users system, you can’t do it. Can you?

You should test your program on different types of computers, and different operating systems, if your program is multi-platform. On some computers you find that there is some DLL missing. You may discover that your Swing application, looking beautiful on Ubuntu, looks messed up on Windows. You may notice that your software takes ages to open up, or that your game is running to fast, on some computers.

All this just increases your work. You may have to go back, add code or files to ensure that everything goes fine. But this extra effort just increases the usability of your software, which is very important.

That’s all for the differences. Best of Luck for your release build!

Posted in Programming | Tagged , , , , | 6 Comments

Starting Apache Derby Embedded in JAR Programmaticaly

In my last post Packaging Java application with Apache Derby as JAR Executable using Eclipse, the code that I used does not start the server at port 1527, by itself, when the JAR is launched. So I have added a few lines to accomplish this.

server = new NetworkServerControl(InetAddress.getByName("localhost"), 1527);
server.start(null);

(Entire code below)

One more thing that I missed out was, that on every users computer the Database is supposed to be created initially. Also the table, has to be created, if it does not exists. So the first time, a user launches JAR (the simple app we made) the database has to created as well as all the required table should be created and populated with content. (Do, read important points below)

So here is the entire code, which

  1. Starts the server
  2. Creates database
  3. Creates table
  4. Inserts values
  5. Queries the table
  6. Closes connection, and shuts down server
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JOptionPane;
import org.apache.derby.drda.NetworkServerControl;


public class Test {
	
	public static void main(String[] args) {

	    NetworkServerControl server = null;
            Connection conn = null;
	    PreparedStatement prestat = null;
	    Statement stmt = null;
	    ResultSet result = null;

	    try {
			server = new NetworkServerControl(InetAddress.getByName("localhost"), 1527);
			server.start(null);
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	    
	    try {
	        Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
	    } catch (InstantiationException e) {
	        e.printStackTrace();
	    } catch (IllegalAccessException e) {
	        e.printStackTrace();
	    } catch (ClassNotFoundException e) {
	        e.printStackTrace();
	    }
	    try {
	        conn = DriverManager.getConnection("jdbc:derby://localhost:1527/MyDbTest;create=true");
	        
	        stmt = conn.createStatement();
	        try {
	        	stmt.execute("CREATE TABLE newTestTable(id int primary key, name varchar(20))");
	        } catch (Exception e) {
	        	//e.printStackTrace();
	        }
	        try {
	        	stmt.execute("INSERT INTO newTestTable VALUES(10, 'Hey,'), (20, 'Look I changed'), (30, 'The code!')");
	        } catch (Exception e) {
	        	
	        }
	        	        
	        prestat = conn.prepareStatement("SELECT * FROM newTestTable");
	        result = prestat.executeQuery();
	        
	        StringBuilder builder = new StringBuilder();
	        while (result.next())
	        {
	        	builder.append(result.getInt(1) + ", " + result.getString(2));
	        	builder.append('\n');
	        }
	        
	        JOptionPane.showMessageDialog(null, builder.toString());
	        
	        result.close();
	        result = null;
	        prestat.close();
	        prestat = null;
	        conn.close();
	        conn = null;
	        
	        server.shutdown();
	        
	    } catch (SQLException e) {
	        e.printStackTrace();
	    } catch (Exception e) {
			e.printStackTrace();
		}
	    finally{
	        if (result != null){
	            try { result.close();} catch (SQLException e){;}
	            result = null;
	        }
	        if (prestat != null){
	            try { prestat.close();} catch (SQLException e){;}
	            prestat = null;
	        }
	        if (conn != null){
	            try {conn.close();} catch(SQLException e) {;}
	        conn = null;
	        }
	    }
	
	}
	
}

IMPORTANT POINTS to note about above program

  1. The code is made small deliberately, hence not very neat. You should break down your logic into methods. Like for inserting values, there should be a separate method.
  2. SQL queries should be handled for exceptions. For eg, if you do not handle exception for query to “CREATE TABLE”, your program would work for first launch. But subsequent launches will terminate the application. Because the table is already present. Also “INSERT INTO” needs to be handled for exception, where duplicate rows might be getting inserted.
  3. Lastly your program, is not going to directly insert data, or search for it. You would be processing user data, and then doing query. I presented a ultra simple case.

And if you make your own great JAR app, don’t forget to share with all of us, here in comments 🙂

Posted in Programming | Tagged , , , , | 19 Comments

Packaging Java application with Apache Derby as JAR Executable using Eclipse

This Tutorial is continuation of tutorial on Installing and using Apache Derby with Eclipse. So check it out, if you haven’t already.

The code I used in the video.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.swing.JOptionPane;

public class Test {

	public static void main(String[] args) {

        Connection conn = null;
	    PreparedStatement prestat = null;
	    ResultSet result = null;

	    try {
	        Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
	    } catch (InstantiationException e) {
	        e.printStackTrace();
	    } catch (IllegalAccessException e) {
	        e.printStackTrace();
	    } catch (ClassNotFoundException e) {
	        e.printStackTrace();
	    }
	    try {
	        conn = DriverManager.getConnection("jdbc:derby://localhost:1527/MyDbTest;");

	        prestat = conn.prepareStatement("SELECT * FROM testTable");
	        result = prestat.executeQuery();

	        StringBuilder builder = new StringBuilder();
	        while (result.next())
	        {
	        	//System.out.println();
	        	builder.append(result.getInt(1) + ", " + result.getString(2));
	        	builder.append('\n');
	        }

	        JOptionPane.showMessageDialog(null, builder.toString());

	        result.close();
	        result = null;
	        prestat.close();
	        prestat = null;
	        conn.close();
	        conn = null;

	    } catch (SQLException e) {
	        e.printStackTrace();
	    }
	    finally{
	        if (result != null){
	            try { result.close();} catch (SQLException e){;}
	            result = null;
	        }
	        if (prestat != null){
	            try { prestat.close();} catch (SQLException e){;}
	            prestat = null;
	        }
	        if (conn != null){
	            try {conn.close();} catch(SQLException e) {;}
	        conn = null;
	        }
	    }

	}

}

Also check my related post Starting Apache Derby Embedded in JAR Programmaticaly

Posted in Programming | Tagged , | 3 Comments

Installing and using Apache Derby with Eclipse

Here is the code in the Video.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class Test {
	
	public static void main(String[] args) {

        Connection conn = null;
	    PreparedStatement prestat = null;
	    ResultSet pw = null;

	    try {
	        Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
	    } catch (InstantiationException e) {
	        e.printStackTrace();
	    } catch (IllegalAccessException e) {
	        e.printStackTrace();
	    } catch (ClassNotFoundException e) {
	        e.printStackTrace();
	    }
	    try {
	        conn = DriverManager.getConnection("jdbc:derby://localhost:1527/MyDbTest;");

	        prestat = conn.prepareStatement("SELECT * FROM testTable");
	        pw = prestat.executeQuery();
	        
	        while (pw.next())
	        {
	        	System.out.println(pw.getInt(1) + ", " + pw.getString(2));
	        }
	        
	        pw.close();
	        pw = null;
	        prestat.close();
	        prestat = null;
	        conn.close();
	        conn = null;

	    } catch (SQLException e) {
	        e.printStackTrace();
	    }
	    finally{
	        if (pw != null){
	            try { pw.close();} catch (SQLException e){;}
	            pw = null;
	        }
	        if (prestat != null){
	            try { prestat.close();} catch (SQLException e){;}
	            prestat = null;
	        }
	        if (conn != null){
	            try {conn.close();} catch(SQLException e) {;}
	        conn = null;
	        }
	    }

	}
}

I have added a post on Packaging Java application with Apache Derby as JAR Executable using Eclipse, which is a continuation of this post. Do check it.

Posted in Programming | Tagged , , | 7 Comments

Simulating Half Adder using VHDL

Posted in Programming, Video | Tagged | Leave a comment

Time Comparison of Quick Sort, Insertion Sort and Bubble Sort

Comparing different sorting algorithms for time performance has always been amusing. It has been done tons of time. But you should try it out for yourself. Apart from fun, this comparison is very useful in real life. Companies and organisations need to sort and search data all the time. Thus it makes sense to compare and find the best suitable sorting method.

First let me show you the result in a neat graph (using MS Excel charts), displaying time (on y-axis) v/s list size (on x-axis).

comparison

If you are done analysing the graph, please note following points

  • The x-axis represents the number of elements sorted.
  • The x-axis is not linear (nor logarithmic). Its random, you see 1,000 then 5,000 then 10,000 and so on up to 3,00,000. The last three entries are linear however, and shows the highlight feature of the graph. The difference in the three algorithms performance.
  • Quick Sort seems to not want to let go off the axis. It is not a mistake, it is for real.
  • Bubble sort’s curve would make a dream come true graph for a company’s profit. Winking smile

Here I reproduce the result in tabular form –

Length Bubble Sort Insertion Sort Quick Sort
1000 0 0 0
5000 0.145 0.045 0
10000 0.6 0.18 0
50000 14.05 4.25 0.01
100000 56.9 17.62 0.02
200000 229.44 69.12 0.05
300000 513.34 154.22 0.065

Variations in numbers (time recorded)

Consider Insertion Sort’s time taken for 5000 integers, 0.045 seconds. This is an average value. Due to other processes going on at the same time as comparison, the recorded time varies during each run. It also varies from computer to computer (mine one is a decent one though, Intel i3 with 4 GB of RAM). Like in one execution, above time was recorded as 0.04 sec and in other it was 0.05 sec. Same goes for all the time values. In effect I have averaged the time taken in the 4 executions. For greater accuracy keep the number of samples to a minimum 10 (although I leave it to you). And also the code should be executed on a variety of computers and Operating Systems (again I leave that for you). However the differences are so pronounced that a variation of 5-10% does not affect the end result.

The big question?

You must wonder why I chose the above three algorithms for comparison. Why not merge sort (arguably the fastest sorting algorithm), or heap sort? And pray, why include Bubble Sort at all??

For one the beginners should know that their favourite sorting (Bubble sort), is umm, well, pathetic and un-acceptable. Second, that quick sort is indeed quick. And I had to take some medium performing algorithm, so Insertion Sort was chosen. All three of them are quite popular and easy to understand.

Give me the code

Yeah sure, here it is:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

long length = 1000;
const long max_length = 300000;

int list[max_length];

void read()
{
    ifstream fin("random.dat", ios::binary);
    for (long i = 0; i < length; i++)
    {
        fin.read((char*)&list[i], sizeof(int));
    }
    fin.close();
}

void bubbleSort()
{
    int temp;
    for(long i = 0; i < length; i++)
    {
        for(long j = 0; j < length-i-1; j++)
        {
            if (list[j] > list[j+1])
            {
                temp        = list[j];
                list[j]     = list[j+1];
                list[j+1]   = temp;
            }
        }
    }
}

void insertionSort()
{
    int temp;
    for(long i = 1; i < length; i++)
    {
        temp = list[i];
        long j;
        for(j = i-1; j >= 0 && list[j] > temp; j--)
        {
            list[j+1] = list[j];
        }
        list[j+1] = temp;
    }
}

long partition(long left, long right)
{
    int pivot_element = list[left];
    int lb = left, ub = right;
    int temp;

    while (left < right)
    {
        while(list[left] <= pivot_element)
            left++;
        while(list[right] > pivot_element)
            right--;
        if (left < right)
        {
            temp        = list[left];
            list[left]  = list[right];
            list[right] = temp;
        }
    }
    list[lb] = list[right];
    list[right] = pivot_element;
    return right;
}

void quickSort(long left, long right)
{
    if (left < right)
    {
        long pivot = partition(left, right);
        quickSort(left, pivot-1);
        quickSort(pivot+1, right);
    }
}

int main()
{
    double t1, t2;

    for (length = 1000; length <= max_length; )
    {
        cout << "\nLength\t: " << length << '\n';

        read();
        t1 = clock();
        bubbleSort();
        t2 = clock();
        cout << "Bubble Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";

        read();
        t1 = clock();
        insertionSort();
        t2 = clock();
        cout << "Insertion Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";

        read();
        t1 = clock();
        quickSort(0, length - 1);
        t2 = clock();
        cout << "Quick Sort\t: " << (t2 - t1)/CLK_TCK << " sec\n";

        switch (length)
        {
        case 1000 :
            length = 5000;
            break;
        case 5000 :
            length = 10000;
            break;
        case 10000 :
            length = 50000;
            break;
        case 50000 :
            length = 100000;
            break;
        case 100000 :
            length = 200000;
            break;
        case 200000 :
            length = 300000;
            break;
        case 300000 :
            length = 300001;
            break;
        }
    }

    return 0;
}

I encourage you to copy the code (modify it to suit your needs), compile it with your choice of compiler and execute it. And share the results with us. I will be glad to showcase here what you found (and how fast your computer runs Smile)

IMPORTANT : The above code requires a file ‘random.dat‘ which contains 3,00,000 integers stored randomly. This file is read each time before a sorting is performed. You can download it here http://www.box.net/shared/1n3r3hedv86351iun6f5 or here https://skydrive.live.com/?cid=a976bcd81e2434ba&sc=documents&id=A976BCD81E2434BA%21114# The file is 1.14MB sized.
Alternatively you can generate ‘random.dat‘ file through this code. This way you can generate a bigger file for more numbers.

#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

const size_t length = 300000;

int main()
{
    ofstream fout("random.dat", ios::binary);

    srand(time(NULL));

    int r;
    for (size_t i = 0; i < length; i++)
    {
        r = rand();
        fout.write((char*)&r, sizeof(r));
    }

    fout.close();
    return 0;
}

Also you can download both the codes, there executables and random.dat in this RAR file(1.01 MB) http://www.box.net/shared/31ofn1v53qrdm0y2cdce or here https://skydrive.live.com/?cid=a976bcd81e2434ba&sc=documents&uc=1&id=A976BCD81E2434BA%21116#

WARNING : The total execution time can exceed 20 minutes (or even more) on slow processors. It may seem that program is hung after sorting 50,000 numbers, but it is not so. The screen stops responding because, the bubble sort starts taking longer times (in several minutes). So nothing to worry, just watch a video or two on vimeo (or youtube).

Conclusion

I would conclude this, that

  • Bubble Sort is not suitable in any circumstance. It is an O(n2) algorithm with a large constant. In simple words, time required to perform bubble sort on ‘n’ numbers increases as square of ‘n’. Thus it is quite slow.
  • Insertion Sort is suitable for small files, but again it is an O(n2) algorithm, but with a small constant. Also note that it works best when the file(/numbers) is already almost sorted.
  • Quick Sort amazed me. Didn’t you get amazed?! Well it is an O(n*log(n)) algorithm on an average case and an O(n2) algorithm in the worst case scenario. (Quick sort’s worst case occurs when the numbers are already sorted!!) The graph speaks it all. You need this algorithm when the list is large and time is premium.

Have a nice time comparing!

Posted in Algorithm, Programming | Tagged , , , , , , | 20 Comments

C++ Programming in Linux

Posted in Programming, Video | Tagged , | Leave a comment