[plt-dev] Re: Speed up check-syntax

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Mon Nov 9 17:13:34 EST 2009

Thanks, Eli. That looks nice.

Matthew suggested something similar, but using mzlib/couroutine, where
I use a low-priority gui callback to give the thread the next quantum.


On Mon, Nov 9, 2009 at 4:08 PM, Eli Barzilay <eli at barzilay.org> wrote:
> [Moving to plt-dev.]
> On Nov  9, Robby Findler wrote:
>> I find such behavior annoying in my OS and expect it would be the
>> same in DrScheme. Things will be sluggish while it is loading.
>> Nevertheless, I will try this if the parallelism stuff doesn't pan
>> out.
> 1. I find the delay-on-first-syncheck especially annoying in class.  I
>   always start a new drscheme at the beginning of the class, which
>   means that I'm guaranteed to get the annoying delay.  (And it's a
>   classic case of unjustified delay, since drscheme will sit there
>   for many minutes doing nothing before I get to use it.)  It's at a
>   level where I hesitate to use it -- and on some occasions I
>   pre-arrange myself so that I click it while I speak to mask out the
>   delay.  (Being able to do such things is something that I had to
>   learn as a stutterer...)
> 2. BTW, the status-line message is not showing at all on linux.  I
>   never knew that there was supposed to be such a message.  (I almost
>   never run it on my laptop.)
> 3. IMO, the issue will not be completely resolved with multiple
>   cores.  What if my other core is busy doing something else?  What
>   about school machines that can be very outdated?  What about IO
>   delays, since this does involve mostly IO?
> 4. The usual way to do these things is to have it loaded when it is
>   idle (exactly what Stephen said) -- but then don't just start to
>   load it so everything becomes slow, just do that in little
>   execution chunks which are done only if the system is still
>   otherwise idle.  I think that MzScheme could use some more
>   functionality in this area -- a nice feature to have would be a way
>   for a thread to change its priority where this can also be a "run
>   me only when otherwise idle" (it would be especially nice to have a
>   hierarchy of these: "run me when otherwise idle including 1st-level
>   idle-priority threads, and give me only 20% running time").
> 5. Fantasies aside, I think that it is possible to do a reasonable job
>   for this given the current tools.  The code below looks to me like
>   it should work fine.  It runs a given thunk in the background while
>   drscheme is idle, and using little cpu time so there's no alarming
>   cpu load.  The returned result is a thunk that returns the computed
>   value -- waiting for it (while giving it 100% cpu) if it isn't
>   ready yet.
> 6. To try it, I basically changed "syncheck.ss" with this definition:
>     (define get-xref
>       (run-lazily (lambda ()
>                     (with-handlers ([exn? (lambda (_) #f)])
>                       (load-collections-xref)))))
>   I've tried it in DrScheme (on my Windows laptop, so the delay is
>   more noticeable), and it looks like it works fine.  No need for
>   multicore support...
> 7. Maybe this would be a good addition to `scheme/promise'.
> ;; Run `thunk' when idle, slicing the time to `slice'-second frames,
> ;; using only `use' seconds from each frame.  Return a thunk that
> ;; returns the result of the computation, giving it full cpu if it's not
> ;; ready yet.
> (define (run-lazily thunk #:slice [slice 0.3] #:use [use 0.05])
>  (define idle-evt (system-idle-evt))
>  (define force-sema (make-semaphore 0))
>  (define results #f)
>  (define (work)
>    (with-handlers ([void (lambda (e) (set! results (cons raise e)))])
>      (set! results (cons values (call-with-values thunk list)))))
>  (define (start)
>    (sync idle-evt)
>    (let ([worker (parameterize ([current-thread-group (make-thread-group)])
>                    (thread work))])
>      (thread-suspend worker)
>      (let loop ()
>        ;; rest, then wait for idle time, then resume working
>        (if (eq? (begin0 (or (sync/timeout (- slice use) force-sema)
>                             (sync idle-evt force-sema))
>                   (thread-resume worker))
>                 force-sema)
>          ;; forced during one of these => let it run to completion
>          (thread-wait worker)
>          ;; not forced
>          (unless (sync/timeout use worker) (thread-suspend worker) (loop))))))
>  (define main-thread
>    (parameterize ([current-thread-group (make-thread-group)])
>      (thread start)))
>  (lambda ()
>    (unless (thread-dead? main-thread)
>      (semaphore-post force-sema)
>      (thread-wait main-thread))
>    (apply (car results) (cdr results))))
> --
>          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>                    http://barzilay.org/                   Maze is Life!

Posted on the dev mailing list.