I have been writing some image processing algorithms that run on incoming
video. At 30fps, there is only 33ms to do all processing.
The following Ruby code is typical of the kind of loops being run.
A lookup table is created that maps video input into the desired output.
The image is then iterated over applying the loopup table to each element.
The following script takes 1.6 secs to execute on my PIII 866Mhz.
The equivalent C++ code takes 8 ms to execute.
A factor of 200 difference.
The equivalent Java code takes 15 ms to execute.
I actually increased the image size 10 fold on the Java run and saw 150ms.
10ms timing resolution really bites.
I like Ruby, but it needs to be significantly faster.
Anybody know the main reason why Ruby is so much slower in this example.
Is it the handling of numbers?
Is there overhead calling yield for every pixel?
Is the array lookup not O(1)?
Ruby
···
size = 6404802
image = []
image.fill 0, 0…size
lookup = []
lookup.fill 0, 0…1024
t0 = Time.now
size.times { |i|
image[i] = lookup[image[i]]
}
td = Time.at(Time.now - t0)
puts “etime: #{td.sec}.#{td.usec}”
C++
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
static LARGE_INTEGER m_countsPerSec;
static LARGE_INTEGER m_start;
static LARGE_INTEGER m_end;
void elapsedTimeInit()
{
QueryPerformanceFrequency(&m_countsPerSec);
}
void elapsedTimeMarkStart()
{
QueryPerformanceCounter(&m_start);
}
/**
- returns the elapsed time in microseconds.
*/
unsigned long elapsedTime()
{
LONGLONG delta;
QueryPerformanceCounter(&m_end);
delta = m_end.QuadPart - m_start.QuadPart;
if (delta < 0)
delta = m_countsPerSec.QuadPart + delta;
delta = (LONGLONG)(1000000.0 * delta / m_countsPerSec.QuadPart + 0.5);
return (unsigned long)delta;
}
void main(int argc, char argv[])
{
const int size = 6404802;
short int image = (short int)malloc(sizesizeof(short int));
memset(image, 0, size*sizeof(short int));
short int lookup[1024] = { 0 };
short int *imageIt = image;
short int *last = image + size;
elapsedTimeInit();
elapsedTimeMarkStart();
while (imageIt != last)
{
*imageIt = lookup[*imageIt];
imageIt++;
}
printf("etime: %ld\n", elapsedTime() );
free(image);
}
Java
import java.util.*;
public class Test
{
public static void main(String[] args)
{
int size = 6404802;
short[] image = new short[size];
for (int i=0; i < size; ++i)
image[i] = 0;
short[] lookup = new short[1024];
for (int i=0; i < 1024; ++i)
lookup[i] = 0;
Date t0 = new Date();
for (int i=0; i < size; ++i)
{
image[i] = lookup[image[i]];
}
Date t1 = new Date();
System.out.println("etime: " + (t1.getTime() - t0.getTime()) );
}
}