PlayBASIC V1.65 (Work In Progress) Gallery

Started by kevin, April 03, 2016, 12:01:41 AM

Previous topic - Next topic

kevin





PlayBASIC V1.65  (Work In Progress) Gallery (3rd April, 2016 - 3rd Oct, 2023)


    This thread will document the changes being made for the PlayBASIC 1.65.  



Retail Builds


    See  PlayBASIC V1.65C2b (fourth revision #2) (12th,Sep,2021)

    See  PlayBASIC V1.65C2 (fourth revision) (10th,July,2021)

    See  PlayBASIC V1.65C (third revision) (21st,Oct,2018)

    See  PlayBASIC V1.65B (second revision) (23rd,June,2017)

    See PlayBASIC V1.65 (initial release)




Work In Progress Beta History


   V1.65C3

   See  Beta 9
   See  Beta 8
   See  Beta 7
   See  Beta 5
   See  Beta 4


   V1.65C2
   See  Beta 20
   See  Beta 15
   See  Beta 14
   See  Beta 12



   V1.65C
   See  Beta 41
   See  Beta 24
   See  Beta 22
   See  Beta 20
   See  Beta 4
   See  Beta 3


   V1.65
   See  Beta 57
   See  Beta 55
   See  Beta 54
   See  Beta 52
   See  Beta 51
   See  Beta 50
   See  Beta 49





Retail Upgrade History


    For older upgrade work in progress see,

    See  PlayBASIC V1.64P

    See  PlayBASIC V1.64O

    See  PlayBASIC V1.64N2 & V1.64N3

    See  PlayBASIC V1.64N

    See  PlayBASIC V1.64M

    See  PlayBASIC V1.64L Learning Edition History (Building learning Edition Thread)





Update Mission Statement:


      Runtime Update Objectives:   Faster, Smaller and Static.

            Faster:  Further bridge gap between native (machine code) and byte code execution through runtime.    
           
            Smaller:  Separate command sets from runtime instruction sets.  So runtime is independent of command set implementations.

               Static:  Instruction set, to make translations easy..  finally !





Upgrade Work In Progress Blog Followes



PlayBASIC V1.65 - Beta1/2 - Trig Instruction Set Tweaks


         Like most updates work on the next revision started a day or two after the last one was uploaded and this is no different.    Right off the bat there's a lot to do to get the runtimes where I need them.  Superficially, all I'm doing is making the internal command sets more standardized (static) and hopefully some what cleaner.  

         In the last couple of V1.64P builds we're been testing some updated strands of the instruction set, with pretty positive results.  The nice benefit of those is they don't break translations through PlayBASIC2DLL, meaning it's still compatible with those DLL's.   So in keeping with such changes I've been converting the TRIG function block to same method.    The benefit ranges from small to large,  where a simple Cos() / Sin() function call is marginally quicker, but stacked polar functions are up to double.    Which is SinRadius, SinNewValue styled functions.

         The snaps bellow are of trig threshold death test, where is running each test millions of times..  The gains over V1.64P4  can be up to around twice as fast..   But like most benchmarks the shots aren't very interesting.    (Tested on 11 year old athlon 64 system)


kevin


PlayBASIC V1.65 Beta 2 - Instruction Set Tweaks - Comparisons


     Today's little update session was focused around the comparison instruction set,  which is one of the old sections of the code in what in now the legacy runtime.   Didn't take too long to get an alternative version set up and it seems to running as expected.   The updated lay out isn't entirely what I've in mind as that will take a number of compiler & instruction set tweaks,  but there's already a nice gain.

      Here's the test code and some pictures of the test running on the 11 year old athlon...     


PlayBASIC Code: [Select]
   ; ----------------------------------------------------------
; ----------------------------------------------------------
; COMPARE BENCH MARK TESTER
; ----------------------------------------------------------
; ----------------------------------------------------------

MaxTests =100

Size =10000


b=100
B#=b
a=b
a#=b

print A<>B
print A#<>B
print A<>B#
print A#<>B#

print A<B
print A#<B
print A<B#
print A#<B#

print A<=B
print A#<=B
print A<=B#
print A#<=B#


print "String compares:"

a$="aaaa"
b$="bbbb"

print a$=b$
print a$<>b$
print a$<b$
print a$<=b$
print a$>b$
print a$>=b$


print "Done"
; sync
;waitkey
;end



Do
cls

frames++

print "Number Of Tests:"+Str$(Size)
print ""
print ""
print ""

print "Integer and Float Compare Functions ----------------------------"

t=timer()
for lp=0 to Size
result=a=b
result=a=b
result=a=b
result=a=b
result=a=b

result=a#=b
result=a#=b
result=a#=b
result=a#=b
result=a#=b

result=a=b#
result=a=b#
result=a=b#
result=a=b#
result=a=b#

result=a#=b#
result=a#=b#
result=a#=b#
result=a#=b#
result=a#=b#
next
tt1#+=(Timer()-t)
print " Equals:"+str$(tt1#/frames)




t=timer()
for lp=0 to Size
result=a<>b
result=a<>b
result=a<>b
result=a<>b
result=a<>b

result=a#<>b
result=a#<>b
result=a#<>b
result=a#<>b
result=a#<>b

result=a<>b#
result=a<>b#
result=a<>b#
result=a<>b#
result=a<>b#


result=a#<>b#
result=a#<>b#
result=a#<>b#
result=a#<>b#
result=a#<>b#


next
tt2#+=(Timer()-t)
print " Not Equals:"+str$(tt2#/frames)




t=timer()
for lp=0 to Size
result=a<b
result=a<b
result=a<b
result=a<b
result=a<b

result=a#<b
result=a#<b
result=a#<b
result=a#<b
result=a#<b

result=a<b#
result=a<b#
result=a<b#
Login required to view complete source code




kevin

#2
  PlayBASIC V1.65 Beta 3/4 - DATA Instruction Set

 After picking through some of the easier to convert blocks of the runtime instruction set I've come to that wall where the remaining changes can't be as easily accomplished.   Meaning to process further down the rabbit hole, means changing the compiler/runtime and instruction sets.   Making everything slower.. and tedious..   It's not all bad news though,  there's a lot of code that can be harvested, tweaked into shape.  

  Before getting into the current WIP,  I was able to make some more tweaks to the comparison instruction set and compiler to remove a bogus state temp that was in the previous bench mark and I guess all legacy builds.   The state was only created when using the compare in a write expression  (ie  Result = A$ <> b$ ), which doesn't happen often in real life.  But it was getting in the way of the  bench..  Anyway, after that applied the same loops peel back about 2 milliseconds from the loop.  So the demo runs in about 18-19 FPS.  On the old test box..    


  Looking through the instruction set here's only about 5 or 6 blocks that need to be converted now.     Annoyingly a lot of instructions are interdependent making them a house of cards, so if you only change one part, it'll break other parts badly.   Which was the main problem back in the initial  PB-> PBFX translation.     This time though all the main command set is detached from the runtimes already (thanks PB2DLL), while still part of the instruction set, they're not same led balloon hanging around the neck of the translation.  

  So the stuff left to do is just thinks like looping,  operators, core maths, array + variable structure accessing opcodes.    There's some legacy pollution though with commands being blocked into the core set that should be.  One of those was the DATA commands.  

  How the compiler/runtime handle data has always been a bit of annoyance,  it made sense a decade ago, but not today.   Sop that's what I've been doing I've been writing a replacement set of functions to handle the DATA heap.  The new format uses less memory and should be quicker generally.   The main thing I didn't like about the old way was it polluted the variable data tables,  as DATA would like in those tables, but that's been changed now...

     The library seems to be working so I'll plug it into the compiler and await the expected crashes tonight sometime.. what joy !



kevin

#3
  PlayBASIC V1.65 Beta 5 - DATA Bench

      The data command set has been replacement with some surprising runtime results, with the bench doubling in performance.   I was expecting it to be quicker, but not by that much,  so that was a nice surprise.    

      The bench code is as follows.   You'll need the attached version as i suspect the entire code would be  too long for a post..  

PlayBASIC Code: [Select]
cls 0
print "DATA SPEED TEST - Waiting"
sync
For lp=1 to 5
wait 1000
Sync
next

Dim Results#(100)
TestStart=Timer()


Dataloop =readdata()

MaxTests =500


; -------------------------------------------------------------------------
; -------------------------------------------------------------------------
Repeat
; -------------------------------------------------------------------------
; -------------------------------------------------------------------------

Cls 0
frames=frames+1

Test=0
Print "Displaying Average Times for "

Print "Current Frame:"+Str$(frames)


print "Data Loops:"+str$(DataLoop)


;--------------------------------------------------------------
;----INTEGER READING-------------------------------------------
;--------------------------------------------------------------

temp=0
ts=Timer()
For i = 0 To MaxTests
restore IntegerValues
for dlp=1 to Dataloop/10
Result=readDATA()
Result=readDATA()
Result=readDATA()
Result=readDATA()
Result=readDATA()

Result=readDATA()
Result=readDATA()
Result=readDATA()
Result=readDATA()
Result=readDATA()

next
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print "READ DATA():"+Str$(results#(test)/frames)
print result
print GetDataPointer()
test=test+1


;--------------------------------------------------------------
;----FLOAT READING---------------------------------------------
;--------------------------------------------------------------
ts=Timer()
For i = 0 To MaxTests
restore FloatValues
for dlp=1 to Dataloop/10
Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()

Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()
Result#=readDATA#()
next
Next i
t=Timer()-ts

Results#(test)=results#(test)+t
Print "READ DATA#():"+Str$(results#(test)/frames)
print result#
print GetDataPointer()
test=test+1

;--------------------------------------------------------------
;---STRING READING---------------------------------------------
;--------------------------------------------------------------

ts=Timer()
For i = 0 To Maxtests
restore StringValues
for dlp=1 to Dataloop/10
Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()

Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()
Result$=readDATA$()

next
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print "READ DATA$():"+Str$(results#(test)/frames)
print result$
print GetDataPointer()
test=test+1


Sync
Until Frames>200

Print "Test Complete"
testEnd=Timer()-TestSTart
Print "Seconds:"+Str$((Timer()-TestStart)/1000.0)
Sync
WaitKey
Waitnokey

end




 

kevin

 PlayBASIC V1.65 Beta 6 - Trig Command Block Bench

       After the DATA command sets the focus has shifting to cleaning house in the core math operations.   There's some stuff in those that just shouldn't still there which fits better in other existing libraries.  Like these bunch of trig commands that lived in the core blocks that have been moved to the new trig block.    Now I wasn't expecting that to alter the performance much, but it does..  

     Bellow in the current trig block bench..  the test is running on the same system using revision 4 of PB1.64P and today's build of PB1.65..   It's a bit of surprise that 1.65 is this much faster..   But I'll take it..


PlayBASIC Code: [Select]
cls 0
print "TRIG Function Bench Mark Waiting"
sync
For lp=1 to 1;;
Sync
wait 1000
next


Dim Results#(100)
TestStart=Timer()



MaxTests=25000

Repeat

Cls 0
frames=frames+1

Test=0
Print "Displaying Average Times for "+str$(Maxtests)+" Tests"

Print "Current Frame:"+Str$(frames)



print ""

temp=0


print "": print ""
print "-- [ COS FUNCTIONS ]-------------------------------"

ts=Timer()
For i = 0 To MaxTests
result#=cos(Angle)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " COS(ANGLE):"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=cos(Angle)*RAdius
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " COS(ANGLE)*RAdius:"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=cos(Angle#)*RAdius#
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " COS(ANGLE#)*RAdius#:"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=cosRadius(Angle,RAdius)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " COSRADIUS(ANGLe,RADIUS):"+Str$(results#(test)/frames)
test=test+1


print "": print ""
print "-- [ SIN FUNCTIONS ]-------------------------------"


ts=Timer()
For i = 0 To MaxTests
result#=sin(Angle)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " SIN(ANGLE):"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=sin(Angle)*RAdius
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " SIN(ANGLE)*RAdius:"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=sin(Angle)*RAdius#
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " SIN(ANGLE#)*RAdius#:"+Str$(results#(test)/frames)
test=test+1

ts=Timer()
For i = 0 To MaxTests
result#=sinradius(Angle,radius#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " SINRADIUS(ANGLE#,Radius#):"+Str$(results#(test)/frames)
test=test+1



print "": print ""
print "-- [ CONVERSION FUNCTIONS ]-------------------------------"


ts=Timer()
For i = 0 To MaxTests
result#=DegreeToRAD(i)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " DegreeToRad:"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=RadToDegree(i0)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " RadToDegree:"+Str$(results#(test)/frames)
test=test+1



print "": print ""
Login required to view complete source code


kevin

#5
 PlayBASIC V1.65 Beta 7 - Raw Memory (Peek/Poke) Command Block Bench

     Here's the results of another block transformation of the Raw memory commands.  In other builds these were combined into a single block but not in the legacy 164 runtimes, but after a bit of messing around they're converted to the new format.    Found a few issues with some of the more odd commands to do with signed bytes,  and of course a made few tweaks to the inners loops.   The compare memory function is about twice a quick now for example.  

    The performance of the raw memory bench mark is much better in V1.65 than V1.64, running about 30 seconds faster.   Tests like copymemory are moving 30 megabyte of memory in the combined test.  So there's a lot of memory access overhead in such demos.   On systems with large CPU data caches that's not really an issue.  

PlayBASIC Code: [Select]
cls 0
print "RAW MEMORY ACCESS Bench Mark Waiting"
sync
For lp=1 to 2;
Sync
wait 1000
next

Dim Results#(100)
TestStart=Timer()

MaxTests =25000

SrcBank =NewBank(MaxTests*4)
SrcPtr =GetBankPtr(SrcBank)

DestBank =NewBank(MaxTests*4)
DestPtr =GetBankPtr(DestBank)


;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
Repeat
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------

Cls 0
frames=frames+1

Test=0
Print "Displaying Average Times for "+str$(Maxtests)+" Tests"

Print "Current Frame:"+Str$(frames)


print ""

temp=0


print "": print ""
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
print "-- [ PEEK FUNCTIONS ]-------------------------------"
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------

ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
result=PeekByte(a)
result=PeekByte(a)
result=PeekByte(a)
result=PeekByte(a)
result=PeekByte(a)

Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " PeekByte():"+Str$(results#(test)/frames)
test=test+1



ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
result=PeekWord(a)
result=PeekWord(a)
result=PeekWord(a)
result=PeekWord(a)
result=PeekWord(a)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " PeekWord():"+Str$(results#(test)/frames)
test=test+1



ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
result=PeekInt(a)
result=PeekInt(a)
result=PeekInt(a)
result=PeekInt(a)
result=PeekInt(a)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " PeekInt():"+Str$(results#(test)/frames)
test=test+1



ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
result#=PeekFloat(a)
result#=PeekFloat(a)
result#=PeekFloat(a)
result#=PeekFloat(a)
result#=PeekFloat(a)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " PeekFlt#():"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
result$=PeekString( a,8)
result$=PeekString( a,8)
result$=PeekString( a,8)
result$=PeekString( a,8)
result$=PeekString( a,8)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " PeekString$():"+Str$(results#(test)/frames)
test=test+1


;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
print "": print ""
print "-- [ POKE FUNCTIONS ]-------------------------------"
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------


ts=Timer()
For i = 0 To MaxTests
a=SrcPtr+i
PokeByte a,i
PokeByte a,i
PokeByte a,i
PokeByte a,i
PokeByte a,i

Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Login required to view complete source code


kevin

#6
  PlayBASIC V1.65 Beta 8 - Remapping Core Maths Function Bench

      Another day and there's another slab of code cross off the translation to do list.  This section focuses on core math functions.   Pretty tedious stuff, from casting, to randoms, range and clipping etc etc.     Had a few gremlins yesterday where all kinds of strange things would occur, but all in all it's coming together pretty well.    It's nice being able to lift similar routines from legacy code.  

      How fast is it..  well, of course the functions bench quicker than PB1.64P4.. You knew that already.. :)  -  One doesn't in this test here, which was the INT() command, but i think that's just from instruction alignment.  Although it's only 2milliseconds slower across 125000 calls, which isn't much.

       Here's the standard test and some snaps of it running on the legacy test system.     Today's V1.65 build runs thos this 35 seconds faster than PB1.64P4...   So yeah.. worth it :)

PlayBASIC Code: [Select]
cls 0
print "CORE MATH Function Bench Mark Waiting"
sync
For lp=1 to 1;;
Sync
wait 1000
next


Dim Results#(100)
TestStart=Timer()



MaxTests=25000

Repeat

Cls 0
frames=frames+1

Test=0
Print "Displaying Average Times for "+str$(Maxtests)+" Tests"

Print "Current Frame:"+Str$(frames)


print ""

temp=0

Angle#=45


print "": print ""
print "-- [ CONVERSION FUNCTIONS ]-------------------------------"

ts=Timer()
For i = 0 To MaxTests
result=int(Angle#)
result=int(Angle#)
result=int(Angle#)
result=int(Angle#)
result=int(Angle#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " INT(Float#):"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To MaxTests
result#=float(i)
result#=float(i)
result#=float(i)
result#=float(i)
result#=float(i)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=Float(i):"+Str$(results#(test)/frames)
test=test+1




ts=Timer()
For i = 0 To MaxTests
result#=ceil(Angle#)
result#=ceil(Angle#)
result#=ceil(Angle#)
result#=ceil(Angle#)
result#=ceil(Angle#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=Ceil(Angle#):"+Str$(results#(test)/frames)
test=test+1



ts=Timer()
For i = 0 To MaxTests
result#=floor(Angle#)
result#=floor(Angle#)
result#=floor(Angle#)
result#=floor(Angle#)
result#=floor(Angle#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=Floor(Angle#):"+Str$(results#(test)/frames)
test=test+1



ts=Timer()
For i = 0 To MaxTests
result#=abs(Angle#)
result#=abs(Angle#)
result#=abs(Angle#)
result#=abs(Angle#)
result#=abs(Angle#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=Abs(Angle#):"+Str$(results#(test)/frames)
test=test+1

ts=Timer()
For i = 0 To MaxTests
result#=Neg(Angle#)
result#=Neg(Angle#)
result#=Neg(Angle#)
result#=Neg(Angle#)
result#=Neg(Angle#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=Neg(Angle#):"+Str$(results#(test)/frames)
test=test+1


Value1#=-100
Value2#=0
Value3#=100



ts=Timer()
For i = 0 To MaxTests
result#=sgn(Value1#)
result#=sgn(Value2#)
result#=sgn(Value3#)
result#=sgn(Value1#)
result#=sgn(Value3#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print " Result#=SIGN(Angle#):"+Str$(results#(test)/frames)
test=test+1


print "": print ""
print "-- [ RANDOM FUNCTIONS ]-------------------------------"


Login required to view complete source code


kevin


PlayBASIC V1.65 Beta 9 -  Loop Processing

      Really cleaning house with the  runtime,  which means souring over the instruction set and execution code sources (since there's 3 builds to choose from),  for the best general solution.    During this session i've dropped in a few more compile time optimizations for the trig functions, just wanted to see how viable my next ideas will be within the existing frame work.  Need not have worried as it went off without a hitch.

   Last nights build runs the 'classic'  bench almost dead on 2 seconds now.   Which is about 250 milliseconds faster than PBV1.64P4 for example.    I seem to recall that VM1 (the first execution engine) from PlayBASIC V1.00 editions took a bout 5 or 6 seconds to execute the same test on the same hardware.    So we've come a long way, but I know it's been ____slow____ going.    Don't worry...   I also find it frustrating also... 


    Tonights focus is on the looping opcodes mainly.    Lean and mean is the order of the evening.   They have to be fast at runtime and nice and easy to decode from the byte code for translation.   It's looking like there's little doubt now we've going to be replacing majority of the core opcodes though (with some cut'paste :) ).  Which will either this occur during upgrade pass or the next.   

      Pressing forward we've going to need community members to step up and test the work in progress versions as they're released.   



kevin

#8
PlayBASIC V1.65 Beta 10 -  Decisions / Comparison bench marking

      Been picking through the core instruction set with fine tooth comb,  a little restructure here and little restore there and  found a few that no longer used opcodes.  Which of course have any place in PB and have such been erased them from existence.    Sp far I've only need to make minor compiler changes to make runtime changes possible.   Which is good and bad,  good that we can trap some legacy issues but bad that we're undoubtable creating some new issues in the process.    But the up side is faster and portable.

       Ok so lets's get to the shots bellow,  which are taken of the IF/THEN  - IF/ENDIF – IF/ElSE/ENDIF – IF ELSE ELSEIF ENDIF styled bench mark.  These types of statements resolve down to a set of branch not equal styles opcodes in the runtime.   I've been able to use one of the newer optimizations in them which as almost doubling the performance of test, which executes in 14 seconds in 1.64P4 and about 8 seconds in yesterdays 1.65 build.      

       I'm confident we can slice some more time off the results, as the test is currently running in hybrid runtime.  So the new opcode execution is sliced into the legacy runtime.    The cost of changing from one to another is rather high and I haven't moved everything across.   Just doing block by block for the time being.


kevin

#9
PlayBASIC V1.65 Beta 11 -  Core Maths Operators – Standard Bench Mark

      The progress this week has been pretty consistent; we're getting through a lot of seemingly small but important tasks (compiler and runtime).   This week we're running the replacement runtime alone side the existing runtime,  which is a lot like the early PBFX builds.   But there's couple of key differences,  such as the shiny new instruction set and externalized command sets.  Meaning we don't have to convert everything all at once to get something working.  Rather we migrate in blocks, which is much easier.  

   
      Today we've got enough of the core runtime working to execute the classic standard test.    For those that don't know, this is just a chunk or pretty bogus code that we've been testing runtime performance with for years now.   They go back as far as 2004..   So a long time.     Which is nice and all, but how does V1.65 perform ??    Well, this test runs almost twice as quick as V1.64P4 on the same hardware.  

       Results:


         1.64  -  2.297   (revision P4)
         1.65  -  1.286    (beta 11)

     So we've pulled a full second out of the execution speed for this example.  I'm not too sure we can get that much faster, would be nice to break the 1 second barrier though.  

     In others tests, we're getting more and more gains.   They seem to be around 2 and bit times quicker.   Like the Data statement bench runs in 14 seconds now compare to the original test of  49 seconds .    It's important to understand that not everything will be that much faster though.    

     Anyway, here's the standard test code again with some boring runtime test pictures.  



PlayBASIC Code: [Select]
; PROJECT : Project1
; AUTHOR : uwdesign
; CREATED : 4/26/2004
; EDITED : 4/29/2016


cls 0
print "Waiting"
sync
For lp=0 to 5
wait 1000
next

Dim TestArrayInt(1000)
Dim TestArrayFloat#(1000)

Dim Results#(100)
TestStart=Timer()



MaxTests=10000

Repeat

Cls 0
frames=frames+1

Test=0
Print "Displaying Average Times for "
;+str$(Maxtests)+" Tests"

Print "Current Frame:"+Str$(frames)

temp=0
ts=Timer()
For i = 0 To MaxTests
temp=temp+1
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print "For Next: Addition:"+Str$(results#(test)/frames)
test=test+1
; print temp


ts=Timer()
For i = 0 To MaxTests
temp=(temp+1)*lp/(lp+1)-lp
Next i

t=Timer()-ts
Results#(test)=results#(test)+t
Print "For Next: Add + Sub + Mult + Div:"+Str$(results#(test)/frames)
test=test+1


ts=Timer()
For i = 0 To Maxtests
If ThisVariable=0
temp=temp+1
EndIf
If ThisVariable=1
Nothing=0
EndIf
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print "For Next: If/Then TRUE and False:"+Str$(results#(test)/frames)
test=test+1

ts=Timer()
Basex#=100
Basey#=100
Radius#=100
For i = 0 To MaxTests
angle=angle+1
X#=BaseX#+(Cos(angle#)*Radius#)
Y#=BaseY#+(Sin(angle#)*Radius#)
Next i
t=Timer()-ts
Results#(test)=results#(test)+t
Print "Basic Trig Functions:"+Str$(results#(test)/frames)
test=test+1



Sync
Until Frames>200

Print "Test Complete"
testEnd=Timer()-TestSTart
Print "Seconds:"+Str$((Timer()-TestStart)/1000.0)
Sync
WaitKey
Waitnokey






kevin

  PlayBASIC V1.65 Beta 13 -  Compiler + Runtime + Instruction Set

   It's only been a month and we're got to point with the update that the easy superficial things are now in short supply, which means turning some attention to how some of the complex parts of the compiler/runtimes work. 

   To the end user we could sum it up like this, basically all the core simple operations have been updated and running in the new VM, which covers everything to do with variables say,  But if you read from an array/call a function then it drops back to the legacy side.   So code that that's interlaces variable and array operations performs very poorly for the time being.    To counter this we need to move those operations to the new VM side. 

   Now what I could do it clean up the instructions a bit and get some cheap gains, but a better solution would be to implement the best solution that fits and performs the best.    Luckly I've already worked this out over the previous rebuilds, which still use high level operations but are more split up.   For example in the legacy VM's when we computes the element from an array, this is generalized.    Which is nice and convient, but add weight to every array access. 

   Looking beyond that, I think some of the new feature like array caching can be further enhanced with some changes to the instruction set/compiler.    Those features had to fit in the legacy design so they're implemented as such, but with the next instruction set should be able to stream line it better..  While will get rid of some of the ambiguous nature of those every common opcodes.

    Anyway, back to it..

kevin

#11
  PlayBASIC V1.65 Beta 15/16 -  Array Functions

 Been working silently away on mostly compiler & runtime things, mixed in with some idea testing.   Rappidly developing a nice list of very handy compiler optimizations that can applied to pretty much any high level and not just BASIC, but I suspect (or would hope) they already exist..  but ya never know.

  This past few sessions have been spent on the Array command set.   In the old editions of PB there was separation of key data tables.   While that was nice and convenient in the legacy editions, it was wasn't so during the building of PB2DLL.  Which meant adding an entirely new set of functions that worked on the DLL side 's  unified data table.   Which means there's number of duplications in the old runtime, with legacy versions that newer versions, so that has to go.  

  So long story short it means converting the compiler & runtimes to use a unified data heap first, then building a single version of the library that can be used from both sides.  Which is where I'm at today..  I've been taking it slow though as there's some good ideas in both version of the libraries that I want to keep.   The newer version does a better job with memory management in some places, but is lazy in others :) ,  which tends help in programs where the programmer doesn't really appreciate what DIM does, or CopyArray does or something.  

   Anyway.. back to it.


     

kevin

#12
  PlayBASIC V1.65 Beta 19 -  Select /Case Blocks


  Well... it's been one of those days. Where you end up starring at the screen for the best part of a day looking what turns out to be a rather obvious issue with the select case runtime evaluation opcodes in the replacement runtime.   Functionally it's the same as before (constants / expressed can be mixed), with the exception the new opcodes only support single data types.   Which means the parser expects the same type of case values/strings as the select variable.

    In older editions of  PlayBASIC numeric data types could be either Integer/Float and would be cast accordingly at runtime.   Which fit nicely in how the older compiler/runtimes worked, but was something I wasn't too keen on, so that's gone.

    Onto the benchmark...  Bellow we have todays WIP bench marks showing integer and Float Select / Case blocks running against IF/ElseIF/EndIF blocks.   The test spreads the calls evenly to get a better idea of the real world performance.   Ideally the closer to the top of tree a match is found the better the loop would perform.    So placing your most frequently used matches first can and will bias performance.  But hopefully that should be common knowledge by now..    

    The results speaks for themselves, todays build is about 4 times quicker than  V1.64P4 on the same legacy hardware.  

 


kevin

#13
PlayBASIC V1.65 Beta 24 -  Bound DLL calls

    Still picking my way through the VM transition,  mostly been working on the dll calling.   The process has been changed somewhat to avoid some extra memory fetching for every call.   Which on the surface seemed easy enough, but it meant rolling a bunch of new support code to make it possible.   Which is par for the course really in optimization terms.  :(

    Anyway, the results are what matter and we've doubled the test code performance.   Which is calling 10K *5 *6  function calls per frame.  On todays build we're getting about 300K function calls at 60fps and about half that V1.64P4 build.   Which is rather  pleasing..  


PlayBASIC Code: [Select]
   maxTests=10000

TestBank=VM_Alloc(MaxTests+256)


; --------------------------------------------------------------------------
do
; --------------------------------------------------------------------------

cls

frames++

// ----------------------------------------------------------------
// -[INTEGER FUNCTION CALLING]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
Status = VM_BankSize(TestBank)
Status = VM_BankSize(TestBank)
Status = VM_BankSize(TestBank)
Status = VM_BankSize(TestBank)
Status = VM_BankSize(TestBank)
next

tt1#+=(timer()-tt)
print " BANK SIZE: "+str$(tt1#/frames)

print "result:"+Str$(Status)


// ----------------------------------------------------------------
// -[SELECT CASE INTEGER]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
Colour=ThisRGB(lp,lp,lp)
Colour=ThisRGB(lp,lp,lp)
Colour=ThisRGB(lp,lp,lp)
Colour=ThisRGB(lp,lp,lp)
Colour=ThisRGB(lp,lp,lp)
next

tt2#+=(timer()-tt)
print " ThisRGB: "+str$(tt2#/frames)



/*

// ----------------------------------------------------------------
// -[SELECT CASE INTEGER]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
Colour=RGB(lp,lp,lp)
Colour=RGB(lp,lp,lp)
Colour=RGB(lp,lp,lp)
Colour=RGB(lp,lp,lp)
Colour=RGB(lp,lp,lp)
next

tt2b#+=(timer()-tt)
print " RGB: "+str$(tt2b#/frames)

*/


// ----------------------------------------------------------------
// -[Poke INT]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
VM_PokeInt(TestBank,lp,ThisValue)
VM_PokeInt(TestBank,lp,ThisValue)
VM_PokeInt(TestBank,lp,ThisValue)
VM_PokeInt(TestBank,lp,ThisValue)
VM_PokeInt(TestBank,lp,ThisValue)
next

tt3#+=(timer()-tt)
print " Poke Int: "+str$(tt3#/frames)




// ----------------------------------------------------------------
// -[Peek INT]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
ThisValue=VM_PeekInt(TestBank,lp)
ThisValue=VM_PeekInt(TestBank,lp)
ThisValue=VM_PeekInt(TestBank,lp)
ThisValue=VM_PeekInt(TestBank,lp)
ThisValue=VM_PeekInt(TestBank,lp)
next

tt4#+=(timer()-tt)
print " Peek Int: "+str$(tt4#/frames)







// ----------------------------------------------------------------
// -[Poke FLOAT]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
VM_PokeFLt(TestBank,lp,ThisValue#)
VM_PokeFLt(TestBank,lp,ThisValue#)
VM_PokeFLt(TestBank,lp,ThisValue#)
VM_PokeFLt(TestBank,lp,ThisValue#)
VM_PokeFLt(TestBank,lp,ThisValue#)
next

tt5#+=(timer()-tt)
print " Poke Flt: "+str$(tt5#/frames)




// ----------------------------------------------------------------
// -[Peek INT]------------------------------------------
// ----------------------------------------------------------------
tt=timer()
For lp =0 to MaxTests
ThisValue#=VM_PeekFlt(TestBank,lp)
ThisValue#=VM_PeekFlt(TestBank,lp)
ThisValue#=VM_PeekFlt(TestBank,lp)
ThisValue#=VM_PeekFlt(TestBank,lp)
ThisValue#=VM_PeekFlt(TestBank,lp)
next

tt6#+=(timer()-tt)
print " Peek Flt: "+str$(tt6#/frames)




print ""
print "FPS:"+STR$(FPS())

Sync

TestEnd++
Login required to view complete source code



kevin

#14
   PlayBASIC V1.65 Beta 26 -  Long Lost Math Function & Operators

        While picking through found a few legacy math functions that hadn't been translated,  that are outside of the 'core math' group since they're not actually functions.   Which is stuff like MOD/MidPoint come to mind, but there's others such as the  SWAP, MidVal with the lowest or higher variants.  

   
         The MidPoint function is one of those legacy functions that i'm not too keen on. Basically it's the average of two values,  where it really should be able to compute a pair,  but a collections of them.  ie  Average(A,B,C,D)  would be the same as (A+B+C+D) / 4    That sorta thing

        The results of the updates have been good, generally twice as quick.  In some cases a manual (inline) of the operation on the new VM is faster than the V1.64P4.   Some extra speed still waiting to be unlocked as the optimizer doesn't understand all of the new instruction set as yet.   Which will win back some extra speed..  Not a lot, but some..