IpSmile
IpSmile

Reputation: 83

Pharo System Tuning Options

I'm new to StackOverflow and looking for tips and helps tuning Pharo 5.0 in Windows Environment.

My PC is running Windows 10, CPU I5-4670K at 4 Ghz, and a Plextor 512G SSD as the C drive where Pharo 5.0 is loaded and running.

Below is a set of codes I used to understand Pharo's behaviors both in performance and computation precision.

  | x y |
  x := 0.
  y := 400000000.
  [1 to: 2000000000 do: [ :i | 
      x := x + 0.2]] timeToRun

took 2 minutes 8.281 seconds to execute. If I knock out one zero from the number of iterations, it took only 1.762 seconds to finish. 10 times more of the iterations used more than 70 times in execution time. It seems that I hit a system boundary such that the time for execution grow much higher than 10 times between the two cases.

Appreciate any tips and helps fine tuning Pharo 5.0 VM so I could reduce such unexpected and undesirable system behaviors?

p.s. During the execution, Windows Task Manager didn't report any changes of the disk activities. Pretty much the execution are all RAM and CPU operations. By the way, unless you have a much faster PC, please don't try to add another zero to the number of iterations, it took so long that I had to break the execution.

Upvotes: 4

Views: 233

Answers (1)

Leandro Caniglia
Leandro Caniglia

Reputation: 14858

Welcome to SO (and to the smalltalk tag!)

First note that temporary y is not playing any role here, so we can simplify a little bit the snippet to

| x |
x := 0.
[1 to: 200000000 * 10 do: [ :i | 
  x := x + 0.2]] timeToRun

which you compared against

| x |
x := 0.
[1 to: 200000000 * 1 do: [ :i | 
  x := x + 0.2]] timeToRun

The reason why the first version is not just 10 times slower that the second is that in the former the block variable i moves from the SmallInteger domain to the LargeInteger one. So, every time the block increments i, when i has surpassed the SmallInteger boundary, the addition i := i + 1 that takes place here involves LargeInteger arithmetic, which is slower than the SmallInteger one.

And how many times does the LargeInteger arithmetics take place? Well, to calculate that we only need to subtract SmallInteger maxVal from 200000000 * 10:

(200000000 * 10) - SmallInteger maxVal  = 926,258,177

meaning that Pharo is performing that number of operations on the large integer i.

Note that if we had had instead

| x |
x := 0.
[
  10 timesRepeat: [1 to: 200000000 * 1 do: [ :i | x := x + 0.2]]
] timeToRun

we would have spent about 10 times the speed of one iteration.


ADDENDUM

Please do not take the explanation above as suggesting that LargeInteger arithmetics has a poor performance in Pharo. On the contrary, Pharo does a great job at making such computations efficient.

Behinds the scenes Pharo uses primitives for these operations while presenting the programmer with a unique and consistent view and API of Integer arithmetics. In fact, if you try to do the same in another dialect with no VM support for LargeInteger you will have to wait much (much) longer for the result to get calculated.

Upvotes: 6

Related Questions