[Gc] Does this code look right to you?

Talbot, George Gtalbot at locuspharma.com
Tue Jun 9 09:56:23 PDT 2009


Hey all,

I've been fooling around with generating relative histograms of memory allocation so that I can take a snapshot of my application every once in a while and look, statistically, at where it's allocating memory the most and how this changes over time.

The way I've done this is to add a function to dbg_mlc.c that stores a bunch of random samples in a file.  It works (mostly), but I do seem to get some "weird" stuff in there.

First, I put this in gc_backptr.h:

    /** This structure saves a record of a sampled heap block when
     *  using GC_accumulate_random_backtraces().
     */
    typedef struct
    {
        void*   p;          /* pointer to block */
        size_t  s;          /* size of block */
        int     kind;       /* hb_obj_kind of block */
        int     nstack;     /* number of saved stack addresses */
        void*   stack[0];   /* addresses of callers at allocation */
    } saved_backtrace_record;

    /** Accumulate a series of backtraces from random addresses.
     *
     *  n       -- Number of random backtraces to generate.
     *  path    -- Path to file to store backtraces.
     */
    void GC_accumulate_random_backtraces(int n, const char* path);

And here's GC_accumulate_random_backtraces():

  typedef struct
  {
      saved_backtrace_record    r;
      void*                     stack_storage[NFRAMES];
  } written_record;

  void GC_accumulate_random_backtraces(int n, const char* path)
  {
      FILE* f = fopen(path, "wb");

      if (!f)
      {
          GC_printf("can't open random backtrace file %s\n", path);
      }

      int   i;
      for (i=0; i<n; ++i)
      {
          void*         p;
          register oh * ohdr;
          hdr *         hhdr;

          do
          {
            p = GC_generate_random_valid_address();
            ohdr = (oh *)GC_base(p);
            hhdr = HDR(ohdr);
          } while (hhdr->hb_flags & (FREE_BLK | WAS_UNMAPPED));

          written_record    w;
          int j;

          w.r.p = p;
          w.r.s = ohdr->oh_sz;
          w.r.kind = hhdr->hb_obj_kind;
          w.r.nstack = NFRAMES;

          for (j=0; j<NFRAMES; ++j)
          {
              w.r.stack[j]    = (void*) (ohdr->oh_ci[j].ci_pc);
          }

          fwrite((void*)&w, sizeof(written_record), 1, f);
      }

      fclose(f);
  }

A few questions:

* Is my above test for FREE_HBLK and WAS_UNMAPPED right to filter out
  free-list blocks?
* I always get about 5-10% of sampled addresses with a very large number
  in the recorded size of the block, or 0 as the size of the block.  How
  reliable is GC_generate_random_valid_address() for picking out actual
  heap blocks?
* Is my use of GC_base(p) and HDR(ohdr) correct?

I also wrote a simple tool which can generate a histogram of call sites weighted by memory usage.  If anybody finds this interesting, I'd be glad to submit it as a patch.

Is it acceptable that the tool would be in C++ rather than C?  (It's a fair bit simpler that way...)

Thanks very much in advance if you can help.

--
George T. Talbot
<gtalbot at locuspharma.com>





More information about the Gc mailing list