2013-11-21

Java on Mac OSX

Notes to myself about Java on Mac OS X since I always forget and have to Google it every time.

  • How do you find all the Java installed on your Mac?
    /usr/libexec/java_home -V

  • How do you set JAVA_HOME to a specific version?
    export JAVA_HOME=`/usr/libexec/java_home -v 1.6`

  • How do you execute a specific version of Java to run?
    /usr/libexec/java_home -v 1.6 --exec javac -version

  • What is the difference between the Java in /System/Library and /Library?
    The Java in /System/Library is the version of Java from Apple. Apple uses it for its system runtime so do not touch or modify it.  The Java in /Library is what you installed from Sun.

  • Where do you put Java Extensions?
    In directory /Library/Java/Extensions

2013-11-20

Auditing Unix input/output

When accessing a customer's Unix server, it is helpful to allow the customer to audit the commands you execute on the server.

To log all your command line inputs and output to a file, use the command

script filename

This will log all your inputs and output into a log file named filename. (Of course replace filename with whatever you want the file name to be).

To finish with logging your commands, type

exit

To share a Unix screen terminal, so the customer can see your inputs and output in real-time, use the screen command.

  1. You and the customer log in as the same Unix user in ssh
  2. You type in the command

    screen -d -m -S myscreenname
    screen -x myscreenname

    (Of course replace myscreenname with whatever you want the screen name to be).
  3. The customer types the command

    screen -x myscreenname
  4. To finish with sharing your Unix terminals, type in the command

    exit
The great feature of screen is that the customer can type in commands from his Unix terminal and you can see the output on your screen. It is an excellent way to do pair-administration.

If you want to use both script and screen at the same time, run the screen command first. The script command will not record the screen inputs/outputs if it is executed first.

How to get rid of color in ls

 Many Unix administrators will force the command  "ls" to automatically output with colors by adding the following alias to the ~/.bashrc

alias ls='ls --color'

To make "ls" not display colors for your session, type in the follow command at the command prompt

unalias ls

2013-11-17

Oracle PL/SQL best practice: Select statements

Question:
What is the best way to do SQL select statements in Oracle PL/SQL?

Answer:
For best performance of select statements returning many rows, use the PL/SQL fetch bulk collect with limit.

DECLARE
    CURSOR hr_employees_cur IS
        SELECT first_name, last_name, hire_date, salary
        FROM hr.employees;
        
    TYPE hr_employees_rec IS record(
        first_name hr.employees.first_name%TYPE,
        last_name hr.employees.last_name%TYPE,
        hire_date hr.employees.hire_date%TYPE,
        salary hr.employees.salary%TYPE
    );
    
    batchSize CONSTANT PLS_INTEGER := 100;    
    TYPE hr_employees_vat IS VARRAY(100) OF hr_employees_rec;    
    hr_employees hr_employees_vat;
    
BEGIN
    OPEN hr_employees_cur;
    LOOP
        FETCH hr_employees_cur BULK COLLECT INTO hr_employees LIMIT batchSize;
        FOR i IN 1 .. hr_employees.COUNT()
        LOOP
            IF ( hr_employees(i).salary > 10000 AND
                 hr_employees(i).hire_date > TO_DATE('15-04-1999', 'DD-MM-YYYY') )
            THEN
                sys.dbms_output.put_line(
                  'New employee over salary limit: ' || 
                   hr_employees(i).first_name || 
                   ' ' || 
                   hr_employees(i).last_name);
            ELSIF ( hr_employees(i).salary < 2400 AND
                    hr_employees(i).hire_date > TO_DATE('15-04-1999', 'DD-MM-YYYY') )
            THEN
                sys.dbms_output.put_line(
                  'New employee under salary limit: ' || 
                   hr_employees(i).first_name || 
                   ' ' || 
                   hr_employees(i).last_name);                     
            END IF;
        END LOOP;
        
        EXIT WHEN hr_employees.COUNT() < batchSize;
    END LOOP;
    
    CLOSE hr_employees_cur;

END;

Notes:
  1. Fetch bulk collect performs the best because it reduces context switching between the PL/SQL and SQL engine. When PL/SQL executes a SQL statement, like in a select SQL fetch, the PL/SQL engine has to pass the processing to the separate SQL engine.  The passing of processing between the PL/SQL and SQL engine is called context switching and it is CPU expensive. Executing a 10,000 row select fetch in a loop results in 10,000 context switches.  Bulk collect fetch batches multi-row select fetches into 1 context switch.
  2. Limit is needed so the bulk collect fetch does not consume excessive per-session memory for select queries that returns a large number of rows.
  3. A batch size of 100 is a good balance between memory and performance. Increasing the batch size above 100 usually leads to diminishing returns in performance.
  4. Unfortunately, Oracle VARRAY does not accept a variable as its initial size.
  5. Oracle recommends exiting the loop via the VARRAY.COUNT instead of CURSOR%NOTFOUND.
  6. Oracle 10g by default (plsql_optimize_level=2) optimizes cursor for-loops to speeds comparable to fetch bulk collect with limit of 100 and with less code.  If you do not need to tune the bulk collect limit size, the cursor for-loop is a good compromise between fast code creation/maintainability and runtime performance.

    The above example using cursor for-loops
DECLARE
    CURSOR hr_employees_cur IS
        SELECT first_name, last_name, hire_date, salary
        FROM hr.employees;
BEGIN
    FOR hr_employees_rec IN hr_employees_cur
    LOOP
            IF ( hr_employees_rec.salary > 10000 AND
                 hr_employees_rec.hire_date > TO_DATE('15-04-1999', 'DD-MM-YYYY') )
            THEN
                sys.dbms_output.put_line(
                  'New employee over salary limit: ' || 
                   hr_employees_rec.first_name || 
                   ' ' || 
                   hr_employees_rec.last_name);
            ELSIF ( hr_employees_rec.salary < 2400 AND
                    hr_employees_rec.hire_date > TO_DATE('15-04-1999', 'DD-MM-YYYY') )
            THEN
                sys.dbms_output.put_line(
                  'New employee under salary limit: ' || 
                   hr_employees_rec.first_name || 
                   ' ' || 
                   hr_employees_rec.last_name);                     
            END IF;    
    END LOOP;
END;

Sources:

2013-06-01

Unique Integer Sorting

Question:
Given a file with a set of unique (non-repeating) integers from 1 to 1,0000,000 , how would you sort it?

For example, if the input file contained

420
2001
23
90210
1492

the output should be

23
420
1492
2001
90210

Solution:
This is one of my favorite interview questions since it shows how the interviewee approaches a fairly simple and common sorting problem.

The best answer in my opinion is to use a bit array.  When the words "unique integer" appears, a bit array should be one of your solution considerations. The basic algorithm is

1. Initialize a bit array to a size of 1,000,000 with all the values of 0.
2. Read each number from the file.
3. For each number, set the bit array index for that number to 1. For example, for the number 420, you would set bit_array[420] = 1 . For 2001,you would bit_array[2001] = 1;
4. Once all the numbers are processed, loop through the bit array and output all the indexes that have a value of 1. That is your sorted list of numbers.

In Java, there is a built-in BitSet implementation of a bit array.

// 1. Initialize bit array
final BitSet bitSet = new BitSet(1000000);
        

// 2. Read each number
final int[] intInput = {420, 2001, 23, 90210, 1492};
 

// 3. Set bit array index with each number from step 2
for (int i : intInput) {
    bitSet.set(i);
}
        

// 4. Loop through bit array and display all set values
for(int i = bitSet.nextSetBit(0); i >=0; i = bitSet.nextSetBit(i+1) ) {
    System.out.print(i + "\n");    
}

The algorithm is easy to understand and implement. It is also fast and does not require a lot of memory.

This question comes from the first chapter of Jon Bentley's book, Programming Pearls . It is a book every good programmer should read