The Q6600
Benchmarks Game

fannkuch-redux Pharo Smalltalk program

source code

"* The Computer Language Benchmarks Game
   https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
   contributed by Paolo Bonzini 
   modified by Isaac Gouy *"!

Object subclass: #BenchmarksGame
   instanceVariableNames: ''
   classVariableNames: ''
   poolDictionaries: ''
   category: ''!

Object subclass: #PermGeneratorRedux
   instanceVariableNames: 'timesRotated perm atEnd'
   classVariableNames: ''
   poolDictionaries: ''
   category: 'benchmarks game'!


!PermGeneratorRedux class methodsFor: 'instance creation'!

new: size
   ^self new
      initialize: size;
      yourself! !


!PermGeneratorRedux methodsFor: 'accessing'!

atEnd
   ^atEnd!

maxPfannkuchenTo: output
   | max permutation checksum permCount flipsCount |
   max := 0.
   permCount := 0.
   checksum := 0.
   [self atEnd] whileFalse:
      [permutation := self next.
      permCount := permCount + 1.
      (permCount = 1048576) ifTrue: [permCount := 0].
      flipsCount := permutation pfannkuchen.
      checksum := permCount odd 
         ifTrue: [checksum+flipsCount] 
         ifFalse: [checksum-flipsCount].
      max := max max: flipsCount].
   output print: checksum; nl.
   ^max!

next
   | result |
   result := perm copy.
   self makeNext.
   ^result! !

!PermGeneratorRedux methodsFor: 'initialize-release'!

initialize: size
   perm := (1 to: size) asArray.
   timesRotated := Array new: size withAll: 0.
   atEnd := false.!

makeNext
   | temp remainder |
   "* Generate the next permutation. *"
   2 to: perm size do: [ :r |
      "* Rotate the first r items to the left. *"
      temp := perm at: 1.
      1 to: r - 1 do: [ :i | perm at: i put: (perm at: i + 1) ].
      perm at: r put: temp.

      remainder := timesRotated at: r 
                                put: ((timesRotated at: r) + 1) \\ r.
      remainder = 0 ifFalse: [ ^self ].

      "* After r rotations, the first r items 
         are in their original positions.
      Go on rotating the first r+1 items. *"
   ].

   "* We are past the final permutation. *"
   atEnd := true! !


!BenchmarksGame class methodsFor: 'private'!

fannkuchRedux: n to: output
   ^(PermGeneratorRedux new: n) maxPfannkuchenTo: output! !

!BenchmarksGame class methodsFor: 'initialize-release'!

do: n
   | f |
   f := self fannkuchRedux: n to: Stdio stdout.
   Stdio stdout
      nextPutAll: 'Pfannkuchen(', n printString, ') = ';
      print: f; nl! !


!Array methodsFor: 'benchmarks game'!

pfannkuchen
   | first complement a b k |
   k := 0.
   [ (first := self at: 1) == 1 ] whileFalse: [
      k := k + 1.
      complement := first + 1.
      1 to: first // 2 do: [ :i |
         a := self at: i.
         b := self at: complement - i.
         self at: i put: b.
         self at: complement - i put: a.
      ]
   ].
   ^k! !


!StdioStream methodsFor: 'benchmarks game'!

nl
   self nextPut: Character lf! !
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
Pharo8.0.0 build: 1122, commit: bbcdf97


Sat, 09 May 2020 21:38:10 GMT

MAKE:
cp /opt/src/pharo64-linux-stable/Pharo8.0.0-0-64bit-bbcdf97.image fannkuchredux.pharo_run.image
cp /opt/src/pharo64-linux-stable/Pharo8.0.0-0-64bit-bbcdf97.changes fannkuchredux.pharo_run.changes
ln -s /opt/src/pharo64-linux-stable/Pharo8.0-32bit-bbcdf97.sources .
cat Include/pharo/make.st

| prog |

(SystemWindow windowsIn: World
      satisfying: [:w | w model canDiscardEdits])
   do: [:w | w delete].

   "load program to be measured"
prog := Smalltalk getSystemAttribute: 3.
(prog notNil) ifTrue: [FileStream fileIn: prog].

ImageCleaner cleanUpForRelease.
Smalltalk garbageCollect.
SmalltalkImage current snapshot: true andQuit: true.


/opt/src/pharo64-linux-stable/pharo -headless fannkuchredux.pharo_run.image Include/pharo/make.st fannkuchredux.pharo 2>/dev/null
cat Include/pharo/main.st

BenchmarksGame do: (Smalltalk getSystemAttribute: 3) asInteger.!
SmalltalkImage current snapshot: false andQuit: true!



36.69s to complete and log all make actions

COMMAND LINE:
/opt/src/pharo64-linux-stable/pharo -headless fannkuchredux.pharo_run.image Include/pharo/main.st 12

PROGRAM OUTPUT:
3968050
Pfannkuchen(12) = 65

pthread_setschedparam failed: Operation not permitted
This VM uses a separate heartbeat thread to update its internal clock
and handle events.  For best operation, this thread should run at a
higher priority, however the VM was unable to change the priority.  The
effect is that heavily loaded systems may experience some latency
issues.  If this occurs, please create the appropriate configuration
file in /etc/security/limits.d/ as shown below:

cat <<END | sudo tee /etc/security/limits.d/pharo.conf
*      hard    rtprio  2
*      soft    rtprio  2
END

and report to the pharo mailing list whether this improves behaviour.

You will need to log out and log back in for the limits to take effect.
For more information please see
https://github.com/OpenSmalltalk/opensmalltalk-vm/releases/tag/r3732#linux