This is the mail archive of the gdb-cvs@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]

[binutils-gdb] [Linux] Avoid refetching core-of-thread if thread hasn't run


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1ad3de988d2f41c72de66613c68ed78507a3abbd

commit 1ad3de988d2f41c72de66613c68ed78507a3abbd
Author: Pedro Alves <palves@redhat.com>
Date:   Tue May 24 14:47:57 2016 +0100

    [Linux] Avoid refetching core-of-thread if thread hasn't run
    
    Hacking the gdb.threads/attach-many-short-lived-threads.exp test to
    spawn thousands of threads instead of dozens, I saw GDB having trouble
    keeping up with threads being spawned too fast, when it tried to stop
    them all.  This was because while gdb is doing that, it updates the
    thread list to make sure no new thread has sneaked in that might need
    to be paused.  It does this a few times until it sees no-new-threads
    twice in a row.  The thread listing update itself is not that
    expensive, however, in the Linux backend, updating the threads list
    calls linux_common_core_of_thread for each LWP to record on which core
    each LWP was last seen running, which opens/reads/closes a /proc file
    for each LWP which becomes expensive when you need to do it for
    thousands of LWPs.
    
    perf shows gdb in linux_common_core_of_thread 44% of the time, in the
    stop_all_threads -> update_thread_list path in this use case.
    
    This patch simply makes linux_common_core_of_thread avoid updating the
    core the thread is bound to if the thread hasn't run since the last
    time we updated that info.  This makes linux_common_core_of_thread
    disappear into the noise in the perf report.
    
    gdb/ChangeLog:
    2016-05-24  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/19828
    	* linux-nat.c (linux_resume_one_lwp_throw): Clear the LWP's core
    	field.
    	(linux_nat_update_thread_list): Don't fetch the core if already
    	known.

Diff:
---
 gdb/ChangeLog   | 8 ++++++++
 gdb/linux-nat.c | 9 ++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index dd62824..ba4fc8f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,14 @@
 2016-05-24  Pedro Alves  <palves@redhat.com>
 
 	PR gdb/19828
+	* linux-nat.c (linux_resume_one_lwp_throw): Clear the LWP's core
+	field.
+	(linux_nat_update_thread_list): Don't fetch the core if already
+	known.
+
+2016-05-24  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/19828
 	* linux-tdep.c (find_mapping_size): Delete.
 	(linux_vsyscall_range_raw): Rewrite reading from
 	/proc/PID/task/PID/maps directly instead of using
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 19fe12f..dbadf29 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -1432,6 +1432,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
      status.  Note that we must not throw after this is cleared,
      otherwise handle_zombie_lwp_error would get confused.  */
   lp->stopped = 0;
+  lp->core = -1;
   lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   registers_changed_ptid (lp->ptid);
 }
@@ -3785,7 +3786,13 @@ linux_nat_update_thread_list (struct target_ops *ops)
   /* Update the processor core that each lwp/thread was last seen
      running on.  */
   ALL_LWPS (lwp)
-    lwp->core = linux_common_core_of_thread (lwp->ptid);
+    {
+      /* Avoid accessing /proc if the thread hasn't run since we last
+	 time we fetched the thread's core.  Accessing /proc becomes
+	 noticeably expensive when we have thousands of LWPs.  */
+      if (lwp->core == -1)
+	lwp->core = linux_common_core_of_thread (lwp->ptid);
+    }
 }
 
 static char *


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