Given a plain racket program like

```
#lang racket/base
(require racket/generator
racket/unsafe/ops)
(define (gen-primes-upto n)
(generator ()
(if (= n 2)
(void)
(let ([table (make-vector n #t)]
[sqrtn (inexact->exact (ceiling (sqrt n)))])
(for ([v (in-vector table 2 sqrtn)]
[i (in-range 2 sqrtn)]
#:when v)
(for ([j (in-range (* i i) n i)])
(unsafe-vector-set! table j #f)))
(yield 2)
(for ([v (in-vector table 3 n 2)]
[i (in-range 3 n 2)]
#:when v)
(yield i))))))
(module+ main
(for ([i (in-range 3)])
(time (for ([_ (in-range 100)])
(for ([_ (in-producer (gen-primes-upto 100000) (void))]
[i (in-range 9000)])
void)))))
```

(This is based on a translation of the Python code in My favorite prime number generator - Eli Bendersky's website)

How do I approach optimizing it?

I know Optimization Coach exists for Typed Racket, but not for plain Racket.

I ran this using `raco profile --use-errortrace sieve.rkt`

and got output like

```
Profiling results
-----------------
Total cpu time observed: 1913ms (out of 1954ms)
Number of samples taken: 38 (once every 50ms)
===================================================
Caller
Idx Total Self Name+src Local%
ms(pct) ms(pct) Callee
===================================================
[1] 1863(97.4%) 0(0.0%) (for ...) ...-blog/2023/prime-sieve/sieve.rkt:25:2
(time ...) [2] 100.0%
---------------------------------------------------
(for ...) [1] 100.0%
[2] 1863(97.4%) 0(0.0%) (time ...) ...blog/2023/prime-sieve/sieve.rkt:26:4
(for ...) [3] 100.0%
---------------------------------------------------
(time ...) [2] 100.0%
[3] 1863(97.4%) 0(0.0%) (for ...) ...blog/2023/prime-sieve/sieve.rkt:26:10
(for ...) [4] 100.0%
---------------------------------------------------
(for ...) [3] 100.0%
[4] 1863(97.4%) 1158(60.5%) (for ...) ...blog/2023/prime-sieve/sieve.rkt:27:12
(let ...) [5] 37.9%
---------------------------------------------------
(for ...) [4] 100.0%
[5] 706(36.9%) 0(0.0%) (let ...) ...-blog/2023/prime-sieve/sieve.rkt:9:17
(for ...) [6] 64.3%
(for ...) [7] 35.7%
---------------------------------------------------
(let ...) [5] 100.0%
[6] 454(23.7%) 0(0.0%) (for ...) ...blog/2023/prime-sieve/sieve.rkt:19:19
(yield ...) [8]100.0%
---------------------------------------------------
(let ...) [5] 100.0%
[7] 252(13.2%) 0(0.0%) (for ...) ...blog/2023/prime-sieve/sieve.rkt:12:19
(for ...) [9] 100.0%
---------------------------------------------------
(for ...) [6] 100.0%
[8] 454(23.7%) 454(23.7%) (yield ...) ...og/2023/prime-sieve/sieve.rkt:22:21
---------------------------------------------------
(for ...) [7] 100.0%
[9] 252(13.2%) 252(13.2%) (for ...) ...blog/2023/prime-sieve/sieve.rkt:15:21
---------------------------------------------------
```

which I don't find useful at all, given it always refers to loops or similar. What I'd like to know is if this is hitting some case preventing optimizations (like boxing integers, or performing too much range checking on the vector, or other things). Is looking at the assembly (Compiler Explorer) in Godbolt the only way? (re: Racket now available on Compiler Explorer - #8 by jryans)

I'm used to languages like C++ or Python, where there are rich line-level or instruction level profilers. Thanks!