I have coded an assembler QuickSort and found that is it slower than the array.sort in java. I am wondering if anyone would know of why I cannot match the speed of some of the higher level languages (I am assuming C would probably be quicker also)
I have tested with 1,000,000 * 1024 bytes. I get approx 2 seconds to complete the sort while Array.Sort in Java will do it in about .8 second
I don't think there is any problem in actually moving the data as I have independently tested that and it moves quite quickly.
%macro $copyBytes 3
mov RSI,%1 ; Grab the Src Address
mov RDI,%2 ; Grab the Dst Address
mov rcx,%3 ; Grab the length
%%l:movsb ; Move the data
loop %%l
%endmacro
%imacro $getAddress 2
mov %1,r_Table ; Start of Table to RSI/RDI
mov rax,%2 ; Lower/Upper to RAX
mul r_recordLength ; Multiply by Record Length
add %1,rax ; add offset to RSI/RDI
%endmacro
%define r_recordLength r8
%define r_startPos r10
%define r_noOfBytes r11
%define r_Ubound r15
%define @left r10
%define @right r11
%define @pivotValue r12
%define @prevLeft r13
[section .bss]
d_startPos resq 1
d_noOfBytes resq 1
pivotValue resb 128 ; This gives tha max sortkey size
LeftAddress resq 1
RightAddress resq 1
[section .text]
; Call the recursive SORT
push 0 ; Push the 1st Left
push r_Ubound ; Push the 1st Right
Call _QSort
pop rax
pop rax
;-----------------------------------------------------------------------
; Recursive Sort
;-----------------------------------------------------------------------
_QSort:
mov @left,qword[rsp+16] ; get the Left Index
mov @right,qword[rsp+8] ; get the Right Index
; if left >= right ; Exit when Left is not < Right
cmp @left,@right
jnl .Exit
; pivotValue = RandomNo[ [ left + right / 2 ] ] CALCULATE pivotValue
mov rax,@left ; Grab the left
add rax,@right ; add the right
shr rax,1 ; and divide by 2
$getAddress RSI,rax ; get the address of this slot
$copyBytes RSI,pivotValue,qword[d_noOfBytes] ; and copy it to pivotValue
; prevLeftIdx = [moveThem]
push @left ; preserve the Left index
push @right ; preserve the Right index
call _moveThem ; do the moves
pop @right ; restore the Right index
pop @left ; restore the Left index
mov @prevLeft,rax ; and save the returned value
; -------------------------------------
; Recursive Call - (left, prevLeft - 1)
; -------------------------------------
push @left ; preserve the Left index
push @right ; preserve the Right index
push @left ; push the 1st parameter (Left)
mov rax,@prevLeft ; get the previous left
dec rax ; minus 1
push rax ; push the 2nd parameter
Call _QSort ; Call yourself
pop rax ; Junk this
pop rax ; Junk this
pop @right ; restore the Right index
pop @left ; restore the Left index
; ----------------------------------
; Recursive Call - (prevLeft, right)
; ----------------------------------
push @left ; preserve the Left index
push @right ; preserve the Right index
push @prevLeft ; push the 1st parameter (previous left
push @right ; push the 2nd parameter (Right0
Call _QSort ; Call yourself
pop rax ; Junk this
pop rax ; Junk this
pop @right ; restore the Right index
pop @left ; restore the Left index
.Exit:
_QSort_EXIT:
ret
_moveThem:
; repeat.while (left <= right)
cmp @left,@right ; Compare Left to Right Index
jg .Exit ; exit if Left is > Right
; repeat.while (Key[left] < pivotValue)
; left = left + 1
; end.repeat
.start1:$getAddress RSI,@left ; Get the Start of the record
add RSI,qword[d_startPos] ; add the requested starting position
mov qword[LeftAddress],RSI ; and save it
mov RDI,pivotValue ; Get the start of the pivotValue
mov rcx,qword[d_noOfBytes] ; Grab the length (LOOP Ctr)
cld ; Clear the direction flag - left to right
repe cmpsb ; Compare the String
jnl .cont1 ; If result not < than exit While Loop
inc @left ; get the next table slot
jmp .start1 ; and repeat
.cont1:
cmp @left,@right ; Compare Left to Right Index
jg .Exit ; exit if Left is > Right
; repeat.while (Key[right]> pivotValue)
; right = right - 1
; end.repeat
.start2:$getAddress RSI,@right ; Get the Start of the record
add RSI,qword[d_startPos] ; add the requested starting position
mov qword[RightAddress],RSI ; and save it
mov RDI,pivotValue ; Get the start of the pivotValue
mov rcx,qword[d_noOfBytes] ; Grab the length (LOOP Ctr)
cld ; Clear the direction flag - left to right
repe cmpsb ; Compare the string
jng .cont2 ; If result not > than exit While Loop
dec @right ; get the previous table slot
jmp .start2 ; and repeat
.cont2:
cmp @left,@right ; Compare Left to Right Index
jg .Exit ; exit if Left is > Right
jl .DoTheMove ; Do the move if less than
; No need to do the move if left = right
inc @left ; increment the left
jmp .Exit ; and head for the exit
; if left <= right - SWAP left and right data
.DoTheMove:
mov RSI,qword[LeftAddress] ; grab the Left address
mov RDI,qword[RightAddress] ; grab the Right address
mov rcx,r_recordLength ; and grab the record length
.start3:cmp rcx,8 ; Have we still got 8 bytes to move
jb .start4 ; If not go and pick up the last few bytes
mov rax,qword[RSI] ; grab the left 8 bytes
mov rbx,qword[RDI] ; grab the right 8 bytes
xchg rax,rbx ; swap them over
mov qword[RSI],rax ; put the right 8 bytes to the left
mov qword[RDI],rbx ; put the left 8 bytes to the right
add RSI,8 ; setup RSI for the next 8 bytes
add RDI,8 ; setup RDI for the next 8 bytes
sub rcx,8 ; take 8 away from the counter
jmp .start3 ; and loop around
.start4:cmp rcx,0 ; Have we still got anything to move
jna .cont4 ; If not we are done
mov ah,byte[RSI] ; grab the left byte
mov al,byte[RDI] ; grab the right byte
xchg ah,al ; swap them over
mov byte[RSI],ah ; put the right byte to the left
mov byte[RDI],al ; put the left byte to the right
add RSI,1 ; setup RSI for the next byte
add RDI,1 ; setup RDI for the next bytes
sub rcx,1 ; take 1 away from the counter
jmp .start4 ; and loop around
.cont4:
inc @left ; Next Left
dec @right ; Previous Right
jmp _moveThem ; Back to the Start
.Exit:
mov rax,@left ; Return the Left value
_moveThem_EXIT:
ret
import java.util.Arrays;
class QuickSort {
public static void Sort(String[] strArray, int lowerIndex, int higherIndex)
{
int left = lowerIndex;
int right= higherIndex;
int x;
String pivot, temp;
pivot = strArray[lowerIndex+(higherIndex-lowerIndex)/2];
while (left <= right) {
x = strArray[left].compareTo(pivot);
while (x < 0) {
left++;
x = strArray[left].compareTo(pivot);
}
x = strArray[right].compareTo(pivot);
while (x > 0) {
right--;
x = strArray[right].compareTo(pivot);
}
if (left <= right) {
temp = strArray[left];
strArray[left] = strArray[right];
strArray[left] = temp;
left++;
right--;
}
}
if (lowerIndex < right)
Sort(strArray,lowerIndex,right);
if (left < higherIndex)
Sort(strArray,left,higherIndex);
}
}
public class V2_11 {
public static void main(String[] args) {
String strArray[] = new String[1000001];
String letters[] = {"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"};
String word;
String spaces[] = new String[998];
int random;
//---------------
//Build the Array
//---------------
System.out.println("Filling Array");
System.out.println(java.time.LocalTime.now());
for (int i=0;i < 1000000;i++){
word="";
for (int j=0;j< 26;j++){
random = (int)(Math.random() * 9 + 0);
word=word+letters[random];
}
strArray[i]=word+spaces;
}
System.out.println(java.time.LocalTime.now());
//--------------
//Sort the Array
//--------------
System.out.println("Sorting");
System.out.println(java.time.LocalTime.now());
//---Arrays.sort(strArray);
QuickSort.Sort(strArray,0, 999999);
System.out.println(java.time.LocalTime.now());
//-------------------
//Display some Reults
//-------------------
for (int i=100;i< 110;i++)
{
System.out.println(strArray[i]);
}
}
}
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
struct timeval start, stop;
double secs = 0;
char strArray[1000000][27];
char pivotValue[27];
char temp[27];
int prevLeftIdx;
int moveThem(int left, int right)
{ int x;
while (left <= right) {
x = strcmp(strArray[left],pivotValue);
while (x < 0) {
left++;
x = strcmp(strArray[left],pivotValue);
}
x = strcmp(strArray[right],pivotValue);
while (x > 0) {
right--;
x = strcmp(strArray[right],pivotValue);
}
if (left <= right) {
strcpy(temp,strArray[left]);
strcpy(strArray[left],strArray[right]);
strcpy(strArray[right],temp);
left++;
right--;
}
}
return left;
}
int QuickSort(int left, int right)
{
if (left>=right)
{return 0;}
strcpy(pivotValue, strArray[(left+right)/2]);
prevLeftIdx=moveThem(left,right);
QuickSort(left,prevLeftIdx-1);
QuickSort(prevLeftIdx,right);
}
int main()
{
char letters[26] = "abcdefghijklmnopqrstuvwxyz";
char c_Null[1] = "\0";
char word[27];
int i,j,random;
//---------------
//Build the Array
//---------------
puts("Filling Array");
gettimeofday(&start, NULL);
srand(time(NULL));
for (i=0;i < 1000000;i++){
for (j=0;j< 26;j++){
random = rand() % 24;
word[j] = letters[random];
}
word[j] = *c_Null;
strcpy(strArray[i],word);
}
gettimeofday(&stop, NULL);
secs = (double)(stop.tv_usec - start.tv_usec) / 1000000 + (double)(stop.tv_sec - start.tv_sec);
printf("time taken %f\n",secs);
//--------------
//Sort the Array
//--------------
puts("Sorting");
gettimeofday(&start, NULL);
QuickSort(0, 999999);
gettimeofday(&stop, NULL);
secs = (double)(stop.tv_usec - start.tv_usec) / 1000000 + (double)(stop.tv_sec - start.tv_sec);
printf("time taken %f\n",secs);
//-------------------
//Display some Reults
//-------------------
for (i=0;i<10 ;i++)
{
puts(strArray[i]);
}
}
RESULTS FOR C program
Filling Array
time taken 0.245878
Sorting
time taken 0.473481
aaaagajqpbutmaxxhgjkauwmwg
aaaakestelpvsrgiemafwtujev
aaaamnvrdueegvfilkvsabdomd
aaaapspaurwurvecikmjibkwfk
aaaauclobckwflwushhnhiafws
aaabaiueabmqlumijuhlrvmgtf
aaabcqehhoeegkhpeondnbsqjb
aaabmwxdrcpfxlhbmggxvjcaoc
aaabplwowigaxmpjipqxkntilc
aaacjsuqkmbwnglltqsspvvtlr