I'm able to replicate the effects you describe on my 4-core machine,
but I'm not convinced that it's an issue with places. The effect seems
to be a limitation of running memory-intensive processes on a single
machine.
In particular, I see the same effects if I run multiple instances of
the program at the same time. To make that comparison easier, I used a
variant of `get-avail` that doesn't busy-wait:
(define (get-avail p res)
(cons
(let loop ((avail '()))
(if (null? avail)
(loop (apply
sync
(map (lambda (pl)
(wrap-evt
pl
(lambda (v)
(set! res (cons v res))
(list pl))))
p)))
avail))
res))
That way, running the program for one place keeps just one core busy.
As long as I don't run out of cores, though, the busy-waiting loops
don't matter relative to the allocating loops, as you have observed.
In general, I would expect allocation and garbage collection to
increase contention at the OS and virtual-memory layers. To
double-check whether something in the Racket memory manager makes that
worse than it should be, I tried running a variant of your program in
both Racket and in Gambit. The program is below, and here are the
results when I run between 1 and 4 instances of the program
concurrently via a shell script:
procs Racket Gambit
(v6.3.0.3) (v4.6.6)
1 1152 1558 \ real time in msec
2 1346 1839 | as reported by one instance
3 1620 2077 |
4 2034 2493 /
That's a rough experiment, and it might be interesting to try more
runtime systems, but the results don't suggest that Racket is doing
anything especially out of line.
I also tried inspecting Racket's execution with various performance
tools, and I didn't see anything suspicious, such as excessive system
calls.
Here's the program for the above table:
; Run with `-f` for Racket
; Uncomment this for compiling with Gambit, but it doesn't seem to
; matter much:
; (declare (standard-bindings) (extended-bindings) (block))
(define numbers '(325220 295205 285260
146030 58810 231409
260650 58890 299280
168250 57320 120210
226100 325260 320180
251680 37310 275680
111010 288300 183890
325220 295205 285260
146030 58810 231409
260650 58890 299280
168250 57320 120210
226100 325260 320180
251680 37310 275680
111010 288300 183890))
(define (len v)
(if (pair? v)
1
0))
(define (add-up n)
(let loop ([repeats 10])
(if (zero? repeats)
'done
(begin
(let loop ((res '()) (n n))
(if (= n 0)
(len res)
(loop (cons n res) (- n 1))))
(loop (- repeats 1))))))
(time (for-each add-up numbers))