[racket] first vs car ; last vs cdr ; empty? vs null?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sun Mar 9 11:55:30 EDT 2014

The GC in that first call to `vector-length` is really paying for work
related to allocating the vector.

Normally, a call to `vector-length` wouldn't present an opportunity for
the GC to fire. Combine it with `time`, though, and there are some
allocation points to set up timing. So, unfortunately, the
instrumentation to time the call to `vector-length` is what allows a GC
to happen and produce a misleading timing result.

Meanwhile, since you're running `(collect-garbage)` three times before
starting, you might not expect a GC to be needed after allocating one
big vector (that's still live). But the way the GC works, it's
essentially because a big chunk of memory has been allocated since the
last GC that can make the system perform a major GC --- particularly if
anything else at all is happening in the Racket process, such as a
sandbox-related thread.

In this case, putting a separate `(collect-garbage)` before each `time`
would probably help measure what you intended to measure.

At Sat, 8 Mar 2014 15:03:07 -0500, Greg Hendershott wrote:
> Before posting, I had repeated this multiple times, running this code
> inside a sandbox.
> 
> After seeing your reply, I tried but couldn't repro it at the command line.
> 
> I could still repro it in the sandbox. But with a fresh sandbox, now I
> can't repro it anymore. I guess some mysterious bit of state was
> causing this (but only for the first call to vector-length??).
> 
> I know the rule -- only do serious profiling at the command line. In
> this case I didn't expect it would matter. I figured "some number vs.
> some smaller number" could be due to environment overhead, but not
> "some number vs. 0". However I was wrong.
> 
> On Sat, Mar 8, 2014 at 1:57 PM, Laurent <laurent.orseau at gmail.com> wrote:
> > I get :
> >
> >> (let ((v (time (make-vector 50000000 0))))
> >     (time (vector-length v))
> >     (time (vector-length v))
> >     (time (vector-length v))
> >     (void))
> > cpu time: 188 real time: 191 gc time: 12
> >
> > cpu time: 0 real time: 0 gc time: 0
> > cpu time: 0 real time: 0 gc time: 0
> > cpu time: 0 real time: 0 gc time: 0
> >
> > Which seems consistent to me.
> >
> > Are you trying on the command line?
> >
> > Laurent
> >
> >
> > On Sat, Mar 8, 2014 at 7:35 PM, Greg Hendershott <greghendershott at gmail.com>
> > wrote:
> >>
> >> As for length:
> >>
> >> (for ([i 3]) (collect-garbage))
> >> (let ((ls (time (make-list 50000000 0))))
> >>   (time (length ls))
> >>   (time (length ls))
> >>   (time (length ls))
> >>   (void))
> >>
> >> It's what I would expect:
> >>
> >> cpu time: 6733 real time: 6744 gc time: 6419
> >> cpu time: 141 real time: 141 gc time: 0
> >> cpu time: 145 real time: 145 gc time: 0
> >> cpu time: 142 real time: 142 gc time: 0
> >>
> >> - - - - -
> >>
> >> Next, thinking about 50000000 elements made me think about vectors,
> >> vector? and vector-length.
> >>
> >> This:
> >>
> >> (for ([i 3]) (collect-garbage))
> >> (let ((v (time (make-vector 50000000 0))))
> >>   (time (vector-length v))
> >>   (time (vector-length v))
> >>   (time (vector-length v))
> >>   (void))
> >>
> >> prints:
> >>
> >> cpu time: 182 real time: 183 gc time: 1
> >> cpu time: 315 real time: 315 gc time: 314
> >> cpu time: 0 real time: 0 gc time: 0
> >> cpu time: 0 real time: 0 gc time: 0
> >>
> >> Huh?  The first call to vector-length takes even longer than making
> >> the vector (and, seems to be almost entirely gc).
> >>
> >> I would have guessed that make-vector would create a structure with
> >> the length already stored in it, and all vector-length calls would be
> >> essentially 0.
> >> ____________________
> >>   Racket Users list:
> >>   http://lists.racket-lang.org/users
> >
> >
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.