Page 1 of 4

Speed of PureBasic

Posted: Fri Jan 23, 2004 5:23 am
by davies
Hi,

I was trying to find out how fast PureBasic is compared to other BASIC compilers (e.g., VB, PowerBASIC). Using the trial version I tried to run the following simple programme for a 100 million iteration of a float calculation:

Global xx.l, yy.f, zz.f

yy.f = 1.000001
zz.f = 1

For xx.l = 1 To 100000000
zz.f = zz.f * yy.f
Next

However, due to it being a trial version it is in debugger mode and takes forever (several seconds) even when compiled into an EXE.

The equivalent code in VB takes 300 ms (0.3 sec) on my 2.4 GHz P4.

I would be very grateful if somebody could please compile the above code in PuerBasic and let me know how long it takes to run on your system.

Many thanks in advance.

Search the forums

Posted: Fri Jan 23, 2004 10:38 am
by Iria
This is a frequently asked question and has been done many times before ... search the forums for speed, preformance and you'll find the answers :wink:

Posted: Fri Jan 23, 2004 11:14 am
by davies
Hi Iria,

Thanks for the reply but I searched the forums and nearly all the benchmarks seems to concern integer functions.

I'm specifically interested in floating point maths for some physics simulations I'm doing.

Posted: Fri Jan 23, 2004 11:53 am
by El_Choni
Floating point maths are performed by the FPU no matter what programming language you use, so there'll be no difference between them in that particular subject.

Posted: Fri Jan 23, 2004 12:26 pm
by Psychophanta
Davies, try these examples:

PB:

Code: Select all

y.f=5 
x.f
For I=1 To 500000000 
x+y*1.000001 
Next 

Messagebox_(0,"Hello, World!","",#MB_ICONINFORMATION)
PowerBasic:

Code: Select all

#COMPILE EXE

FUNCTION PBMAIN () AS LONG

Dim starttime AS DWORD
Dim elapsedtime AS DWORD
Dim I AS DWORD
Dim y AS SINGLE
Dim x AS SINGLE
y=5

For I=1 To 500000000
    x=x+y*1.000001
Next


    MSGBOX "Hello, World!"

End FUNCTION
GCC (In windows you can use tha called "minimalize GCC for windows"):

Code: Select all

#include <windows.h>

   int WINAPI WinMain (HINSTANCE hInstance, 
                        HINSTANCE hPrevInstance, 
                        PSTR szCmdLine, 
                        int iCmdShow)

   {

long starttime,elapsedtime, I;
float y=5,x;

//starttime=GetTickCount()

For (I=1;I<=500000000;I++) x=x+y*1.000001;


//elapsedtime=GetTickCount()-starttime

      MessageBox (NULL, "Hello", "Hello Demo", MB_OK);
      Return (0);
   }
You can compare speeds and final executable sizes. But in fact, speed comparison is better done with more complex programs :)

Posted: Fri Jan 23, 2004 5:05 pm
by Wayne Diamond
With all due respect ....

Code: Select all

For xx.l = 1 To 100000000 
zz.f = zz.f * yy.f 
Next
This is a useless test. Why? 1) such code would NEVER exist in a real program (it's a useless loop that does nothing), and 2) such basic code/few instructions would pretty much be converted to the same assembly instructions in each language, so really it's not a very good language comparison method.

At the end of the day, if a program is capable of translating your code into assembly language (as Purebasic does) before compiling it, then you'll struggle to find faster code (unless of course you use INLINE assembly - which Purebasic also supports, so you get the best of both worlds)

Posted: Fri Jan 23, 2004 6:25 pm
by Psychophanta
With all due respect ....
:P

I think you are right about all explained, except in point 1): I think that the fact that a loop doesn't exist in a real program (or is useless for a real program) have nothing to do about that loop is useless or not useless in order to test compiler speed. :?

Posted: Fri Jan 23, 2004 7:32 pm
by Shannara
Lol, good point :) In the current forum, there is only one thread directly testing VB vs PB for simple math functions :) VB won hands down. Then again, VB has such a huge runtime (close to 5 megs in memory) while a simple hello world in PB uses 1 meg.

Posted: Fri Jan 23, 2004 7:35 pm
by Wayne Diamond
Basically what I meant is that this:

Code: Select all

For x = 1 to Whatever
 Do Nothing
Loop
... is basically going to compile to the same assembly-level code, regardless of which compiler you use, so if you're wanting to compare the speed of one language to another, using such a useless loop is probably the worst way to go about it :). Instead, try to use as many complex-but-similar functions (like RIGHT$, MID$, INSTR, etc) - functions that exist in each language and are relatively similar in each language, but have some degree of complexity). This will give a more accurate comparison than that of a loop that does nothing, _but_ at the same time it's also easier to make silly mistakes that may make one compiler seem slower when it actually shouldn't be, so the programmer really should be confident in his code before making such comparisons between multiple compilers, and likewise, you should be confident in their abilities before you take their word for one compiler being faster than another ... :)

Posted: Fri Jan 23, 2004 8:46 pm
by Road Runner
Wayne,
I disagree. The stated need is for fast FP maths.
Although the test loop is trivial it does require that the compiler produce FP code.
If it does it BADLY then that will be shown up by the test.
If it does it WELL then the time will be much the same as for other good compilers.

Davies wishes to know if PB is as good as the others for FP presumably before buying. The test will give such an indication.

String functions, complex or otherwise, are a different matter.

Posted: Fri Jan 23, 2004 11:20 pm
by Psychophanta
Wayne wrote:
...try to use as many complex-but-similar functions (like RIGHT$, MID$, INSTR, etc) - functions that exist in each language and are relatively similar in each language, but have some degree of complexity). This will give a more accurate comparison than that of a loop that does nothing...
And this is a true point.
Road Runner wrote:
Although the test loop is trivial it does require that the compiler produce FP code.
If it does it BADLY then that will be shown up by the test.
If it does it WELL then the time will be much the same as for other good compilers.
That's certain too, but today all good compilers produce FP code quite good, so there should be necessary a clever implementation of a FP testing code, and include FP functions in it, like Abs(), Pow(), logarithms, trigonometric functions, addings, substractings, divs... ...for example to test FP should be good to include 80 or 100 differents equations resolutions as expressions inside a loop which modifies values of variables in the expressions.

Posted: Sat Jan 24, 2004 10:59 am
by Danilo
Wayne Diamond wrote:Basically what I meant is that this:

Code: Select all

For x = 1 to Whatever
 Do Nothing
Loop
... is basically going to compile to the same assembly-level
code, regardless of which compiler you use,
Nope, thats wrong.

Lets take this 2 examples:

Code: Select all

; code 1
For a = 1 To 100000000 
Next

; code 2
For a = 1 To 100000000 
  x + 1
Next
The BEST compilers fully optimize this. Code 1 does nothing,
so the compiler removes the loop completely and uses:
'a = 100000000' instead.
The second code is also useless, the compiler removes it
with: 'a = 100000000 : x + 100000000'
This is what the best compilers do, awesome optimizations.

GOOD compilers use 2 registers for the loop variable 'a'
and 'x'. In the loop, the 2 registers are incremented, and right
after the loop, 'a' and 'x' are both written to memory (in the
place where the variable is saved in memory).

PureBasic (and some other non-optimizing compilers)
run it like it is, both variables are in memory and are incremented
and compared from memory 100000000 times.


Wayne, this IS a *big* difference (and you should know that).
Dont wonder why PB loses against VB and nearly all other
compilers in this, its just logical.
(also tested against 3 C/C++ compilers, PB is always the
last and much slower than any other compiler)

Good compilers have an built-in optimizer that analyzes the code
and loops, and the best compilers check everything possible,
even pairing of generated ASM code and all the important speed stuff.
Not to talk about MMX/SSE/SSE2 directly in the generated main code,
if possible and if the compile target allows it.

PureBasic is just a 'stupid' (from the technical point of view)
translator that replaces "a + 1" with "INC dword [v_a]", there
is no analyzer and optimizer for real logic.

Optimized and intelligent register allocation? No way with PB!
Good compilers would check what is within the loop (function
calls, plain calculations only,...) and decide how many free
registers are needed.
If all registers are used currently, they push 2 registers on stack
that are not needed in the loop and put the 2 variables in it.
Now the loop runs completely in the fast registers, and on loop
end the 2 registers are written to the memory variables ('a' + 'x')
and the 2 saved regs are poped back from stack.

You say this tests are senseless because they do nothing, and
i agree generally (and i told people too), BUT:
loops (repeat...until, for...next, while...wend) are *basic* things
in every language and are used very very strong.
program flow statements are one of the _fundamentals_ of
programming languages, so they must be very high optimized.

If you want to compare speed of languages, you use nearly
always loops. Not empty ones, but loops with contents.
The non-optimized loops in PureBasic will *always* slow down
every test, so chances to win the test are much lower.

People tend to believe PureBasic is fast because it can generate
ASM, and most people dont know ASM - so they have respect
and automatically think its fast (btw: even old GWbasic is very
fast on 1GHz or 3GHz CPU's we have today ;)).
Well, 99% of all compilers generate ASM internally and assemble
it by an assembler after generation. Sometimes the assembler
is built-in (so people dont see that process), sometimes its an
external assembler (borland BASM for Delphi, MASM for Microsoft,
gas (GNU assembler),...).

The big difference: some compilers generate very good ASM code,
others dont do it.

You cant expect too much from compilers that dont optimize
such fundamental things as loops.
PureBasic IS fast, and we have very fast processors today -
0,97 MHz CPU's were in the past (remember C64? :twisted:).

Many things have to get done in the pbcompiler to say its a
good or a very good compiler, but the users cant change that
anyway.
From a technical point of view, the PB compiler is 'OK', but not
good. The very good thing in PB are the many libs with some
hundred commands... and all that platform independent (not perfect
today, but its getting better every release (Win+Linux)).


BTW, before i forget it:
On multitasking operating systems like Win and Linux (well, every
modern OS), the tests many people do are wrong anyway.
There are happening task switches every few milliseconds and
there are always running processes in the background (the operating
system itself for example).
On windows, you have to give your test code realtime priority
to get better results and to be fair:

Code: Select all

SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS)
; test code here
SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)
And the second (very important) thing:
Guys tend to compare speed only, but speed is not everything.
Sometimes there is a very good reason some code is slower,
for example:
If you compare speed of string operations, PureBasic speed should
be OK - but strings are not thread safe in PB (well, nothing
in PB is really thread safe).

Some other compilers make every 'object' (strings) thread-safe,
because many applications use threads. Threads are used very
often to run things in background and to run things at the same
time (multiprocessor), the newest CPUs get extra features for
performing better with threads.

This depends on the compiler you test with (and if you can
enable/disable thread safety), but is very important - you
should remember this while testing.
The fastest code is absolutely useless if it just crashes or gets
corrupt/mixed-up within threads.

Posted: Sat Jan 24, 2004 11:50 am
by blueznl
i smile thesedays at speed comparisons... ok, i was into speed stuff myself at one time, but lately i don't bother that much...

when dealing with speed, one should ask himself NOT: who is fasted, but who is fast enough... if it's fast enough, then other factors come into play...

so ask yourself some other questions...

- is it fast enough?
- easy of use (editor, environment, compiler, designer etc.)
- ease of language (syntax, (in)consistencies, etc.)
- capabilities of the language
- documentation (help files, tutorials, but also forums like these)
- fun factor (do you LIKE the language, or does it feel alien to you)
- does it produce readable code

that last one is often overlooked, and is somewhat part of the fun factor... trust me, code becomes a lot less funny when you can't read it a year later... it's this that bothers me everytime i try c(++)... if i glance at basic, i can quickly grasp what is going on, c(++) always turns out into a puzzling act...

the one thing i miss is realtime syntax checking, the feature i loved so much from gfabasic, it increased the fun factor, and made code by default readable

Posted: Sat Jan 24, 2004 12:39 pm
by Psychophanta
Danilo wrote:
...Good compilers have an built-in optimizer that analyzes the code
and loops, and the best compilers check everything possible,
even pairing of generated ASM code and all the important speed stuff.
Not to talk about MMX/SSE/SSE2 directly in the generated main code,
if possible and if the compile target allows it.

PureBasic is just a 'stupid' (from the technical point of view)
translator that replaces "a + 1" with "INC dword [v_a]", there
is no analyzer and optimizer for real logic. ... ... ...
In other topic about compiler target code speed Fred said that it is easy to optimize code to do what VB does in loops.
QUESTION for who knows: Is Fred working or keeping in mind or in his TODO list, to build an optimizer, analizer, etc, etc. for PB?

Posted: Sat Jan 24, 2004 5:44 pm
by chris_b
Danilo wrote:use 2 registers for the loop variable 'a'
and 'x'. In the loop, the 2 registers are incremented, and right
after the loop, 'a' and 'x' are both written to memory (in the
place where the variable is saved in memory).
Cool - I can now speed up some of my code utilising this knowledge! (Now that I've finally understood how to use the /COMMENTED and /REASM features of Pbcompiler.exe)

BTW do you have a life outside Purebasic? Do you have any time left after coding and also making such detailed replies to many forum posts?