This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: JIT interface slowness


On Mon, Jan 3, 2011 at 2:43 AM, Vyacheslav Egorov <vegorov@chromium.org> wrote:

> I thought that setting a breakpoint requires O(1) not O(n). It's a bit
> disappointing.

I think I've mis-diagnosed the problem slightly -- there is no breakpoint
inserted into every JITted ELF. But there is still a quadratic loop in jit.c:

/* Look up the objfile with this code entry address.  */

static struct objfile *
jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
{
  struct objfile *objf;
  CORE_ADDR *objf_entry_addr;

  ALL_OBJFILES (objf)
    {
      objf_entry_addr = (CORE_ADDR *) objfile_data (objf, jit_objfile_data);
      if (objf_entry_addr != NULL && *objf_entry_addr == entry_addr)
        return objf;
    }
  return NULL;
}

...
static void
jit_inferior_init (struct gdbarch *gdbarch)
...
  /* If we've attached to a running program, we need to check the descriptor to
     register any functions that were already generated.  */
  for (cur_entry_addr = descriptor.first_entry;
       cur_entry_addr != 0;
       cur_entry_addr = cur_entry.next_entry)
    {
      jit_read_code_entry (gdbarch, cur_entry_addr, &cur_entry);

      /* This hook may be called many times during setup, so make sure we don't
         add the same symbol file twice.  */
      if (jit_find_objf_with_entry_addr (cur_entry_addr) != NULL)
        continue;

      jit_register_code (gdbarch, cur_entry_addr, &cur_entry);
    }

This is quadratic if you insert all 1000 JITted ELFs and call the
__jit_debug_register_code() once.

If you call __jit_debug_register_code() after adding every new ELF,
you get N*N*N instead :-(

My gut feeling though is that the really slow operation here is
jit_read_code_entry (which reads target memory) and everything else is
noise in comparison (but I haven't measured it).  Assuming this is so,
you get O(N) if you call __jit_debug_register_code once, and O(N*N) if
you call it after every new ELF.

I think we could do much better if we keep a "shadow" copy of the list of
JITted ELFs in GDB, instead of re-reading it from inferior all the time.

Let me try to come up with a patch ...


> I will have to emit debug information (namely .debug_frame)
> for all code object otherwise gdb is not able to unwind stack properly
> on x64.

This is slightly incorrect: you must emit .eh_frame{,_hdr} for any
x86_64 code if you want stack unwinder to work, but you don't need to emit
any debug info (IOW, .debug_frame is not required).

Cheers,
-- 
Paul Pluzhnikov


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]