Subject: bug#10580: 24.0.92; gdb initialization takes more than one minute at 100% CPU

From: Chong Yidong <[email-masked]>
Date: Fri, 11 May 2012 14:33:52 +0800

Dov Grobgeld <[email-masked]> writes:

> Here are the tests when using the the latest cvs gdb that yields a gdb
> output file of about 800k.
>
> Without gdb-get-source-file-list override: ~139s
> With gdb-get-source-file-list override: ~125s
>
> Thus it is clear that most of the time is taken just reading the
> string into emacs. But doing find-file on the same file is almost
> instantaneous.

Here's another little experiment.  Could you apply the two attached
patches, individually, and see what difference each patch makes?
(Again, with gdb-create-source-file-list at its default of t, and
without any other patches to gdb-mi.el.)

=== modified file 'lisp/progmodes/gdb-mi.el'
*** lisp/progmodes/gdb-mi.el	2012-04-20 10:09:40 +0000
--- lisp/progmodes/gdb-mi.el	2012-05-11 06:21:29 +0000
***************
*** 1918,1923 ****
--- 1918,1925 ----
      (gdb-ignored-notification . "=[-[:alpha:]]+,?\\(.*?\\)\n")
      (gdb-shell . "\\(\\(?:^.+\n\\)+\\)")))
  
+ (defvar gdb-accumulator nil)
+ 
  (defun gud-gdbmi-marker-filter (string)
    "Filter GDB/MI output."
  
***************
*** 1928,1954 ****
  	     (> (length gdb-debug-log) gdb-debug-log-max))
  	(setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
  
!   ;; Recall the left over gud-marker-acc from last time
!   (setq gud-marker-acc (concat gud-marker-acc string))
  
    ;; Start accumulating output for the GUD buffer
    (setq gdb-filter-output "")
-   (let (output-record-list)
  
!     ;; Process all the complete markers in this chunk.
!     (dolist (gdbmi-record gdbmi-record-list)
!       (while (string-match (cdr gdbmi-record) gud-marker-acc)
! 	(push (list (match-beginning 0)
! 		    (car gdbmi-record)
! 		    (match-string 1 gud-marker-acc)
! 		    (match-string 2 gud-marker-acc)
! 		    (match-end 0))
! 	      output-record-list)
! 	(setq gud-marker-acc
! 	      (concat (substring gud-marker-acc 0 (match-beginning 0))
! 		      ;; Pad with spaces to preserve position.
! 		      (make-string (length (match-string 0 gud-marker-acc)) 32)
! 		      (substring gud-marker-acc (match-end 0))))))
  
      (setq output-record-list (sort output-record-list 'gdb-car<))
  
--- 1930,1960 ----
  	     (> (length gdb-debug-log) gdb-debug-log-max))
  	(setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
  
!   ;; Recall the left over output from last time
!   (unless gdb-accumulator
!     (setq gdb-accumulator (get-buffer-create " *gdb output accumulator")))
! 
!   (with-current-buffer gdb-accumulator
!     (goto-char (point-max))
!     (insert string))
  
    ;; Start accumulating output for the GUD buffer
    (setq gdb-filter-output "")
  
!   ;; Process all the complete markers in this chunk.
!   (let (output-record-list marker)
!     (with-current-buffer gdb-accumulator
!       (dolist (gdbmi-record gdbmi-record-list)
! 	(goto-char (point-min))
! 	(while (re-search-forward (cdr gdbmi-record) nil t)
! 	  (setq marker (make-marker))
! 	  (set-marker marker (match-beginning 0))
! 	  (push (list marker
! 		      (car gdbmi-record)
! 		      (match-string 1)
! 		      (match-string 2))
! 		output-record-list)
! 	  (replace-match "\n"))))
  
      (setq output-record-list (sort output-record-list 'gdb-car<))
  
***************
*** 1969,1976 ****
  
      (setq gdb-output-sink 'user)
      ;; Remove padding.
!     (string-match "^ *" gud-marker-acc)
!     (setq gud-marker-acc (substring gud-marker-acc (match-end 0)))
  
      gdb-filter-output))
  
--- 1975,1984 ----
  
      (setq gdb-output-sink 'user)
      ;; Remove padding.
!     (with-current-buffer gdb-accumulator
!       (goto-char (point-min))
!       (while (re-search-forward "^\n" nil t)
!     	(replace-match "")))
  
      gdb-filter-output))

=== modified file 'lisp/progmodes/gdb-mi.el'
*** lisp/progmodes/gdb-mi.el	2012-04-20 10:09:40 +0000
--- lisp/progmodes/gdb-mi.el	2012-05-11 06:32:52 +0000
***************
*** 1904,1923 ****
    (< (car a) (car b)))
  
  (defvar gdbmi-record-list
!   '((gdb-gdb . "(gdb) \n")
!     (gdb-done . "\\([0-9]*\\)\\^done,?\\(.*?\\)\n")
!     (gdb-starting . "\\([0-9]*\\)\\^running\n")
!     (gdb-error . "\\([0-9]*\\)\\^error,\\(.*?\\)\n")
!     (gdb-console . "~\\(\".*?\"\\)\n")
!     (gdb-internals . "&\\(\".*?\"\\)\n")
!     (gdb-stopped . "\\*stopped,?\\(.*?\\)\n")
!     (gdb-running . "\\*running,\\(.*?\n\\)")
!     (gdb-thread-created . "=thread-created,\\(.*?\n\\)")
!     (gdb-thread-selected . "=thread-selected,\\(.*?\\)\n")
!     (gdb-thread-exited . "=thread-exited,\\(.*?\n\\)")
!     (gdb-ignored-notification . "=[-[:alpha:]]+,?\\(.*?\\)\n")
      (gdb-shell . "\\(\\(?:^.+\n\\)+\\)")))
  
  (defun gud-gdbmi-marker-filter (string)
    "Filter GDB/MI output."
  
--- 1904,1925 ----
    (< (car a) (car b)))
  
  (defvar gdbmi-record-list
!   '((gdb-gdb . "^(gdb) \n")
!     (gdb-done . "^\\([0-9]*\\)\\^done,?\\(.*?\\)\n")
!     (gdb-starting . "^\\([0-9]*\\)\\^running\n")
!     (gdb-error . "^\\([0-9]*\\)\\^error,\\(.*?\\)\n")
!     (gdb-console . "^~\\(\".*?\"\\)\n")
!     (gdb-internals . "^&\\(\".*?\"\\)\n")
!     (gdb-stopped . "^\\*stopped,?\\(.*?\\)\n")
!     (gdb-running . "^\\*running,\\(.*?\n\\)")
!     (gdb-thread-created . "^=thread-created,\\(.*?\n\\)")
!     (gdb-thread-selected . "^=thread-selected,\\(.*?\\)\n")
!     (gdb-thread-exited . "^=thread-exited,\\(.*?\n\\)")
!     (gdb-ignored-notification . "^=[-[:alpha:]]+,?\\(.*?\\)\n")
      (gdb-shell . "\\(\\(?:^.+\n\\)+\\)")))
  
+ (defvar gdb-accumulator nil)
+ 
  (defun gud-gdbmi-marker-filter (string)
    "Filter GDB/MI output."
  
***************
*** 1928,1954 ****
  	     (> (length gdb-debug-log) gdb-debug-log-max))
  	(setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
  
!   ;; Recall the left over gud-marker-acc from last time
!   (setq gud-marker-acc (concat gud-marker-acc string))
  
    ;; Start accumulating output for the GUD buffer
    (setq gdb-filter-output "")
-   (let (output-record-list)
  
!     ;; Process all the complete markers in this chunk.
!     (dolist (gdbmi-record gdbmi-record-list)
!       (while (string-match (cdr gdbmi-record) gud-marker-acc)
! 	(push (list (match-beginning 0)
! 		    (car gdbmi-record)
! 		    (match-string 1 gud-marker-acc)
! 		    (match-string 2 gud-marker-acc)
! 		    (match-end 0))
! 	      output-record-list)
! 	(setq gud-marker-acc
! 	      (concat (substring gud-marker-acc 0 (match-beginning 0))
! 		      ;; Pad with spaces to preserve position.
! 		      (make-string (length (match-string 0 gud-marker-acc)) 32)
! 		      (substring gud-marker-acc (match-end 0))))))
  
      (setq output-record-list (sort output-record-list 'gdb-car<))
  
--- 1930,1960 ----
  	     (> (length gdb-debug-log) gdb-debug-log-max))
  	(setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
  
!   ;; Recall the left over output from last time
!   (unless gdb-accumulator
!     (setq gdb-accumulator (get-buffer-create " *gdb output accumulator")))
! 
!   (with-current-buffer gdb-accumulator
!     (goto-char (point-max))
!     (insert string))
  
    ;; Start accumulating output for the GUD buffer
    (setq gdb-filter-output "")
  
!   ;; Process all the complete markers in this chunk.
!   (let (output-record-list marker)
!     (with-current-buffer gdb-accumulator
!       (dolist (gdbmi-record gdbmi-record-list)
! 	(goto-char (point-min))
! 	(while (re-search-forward (cdr gdbmi-record) nil t)
! 	  (setq marker (make-marker))
! 	  (set-marker marker (match-beginning 0))
! 	  (push (list marker
! 		      (car gdbmi-record)
! 		      (match-string 1)
! 		      (match-string 2))
! 		output-record-list)
! 	  (replace-match "\n"))))
  
      (setq output-record-list (sort output-record-list 'gdb-car<))
  
***************
*** 1969,1976 ****
  
      (setq gdb-output-sink 'user)
      ;; Remove padding.
!     (string-match "^ *" gud-marker-acc)
!     (setq gud-marker-acc (substring gud-marker-acc (match-end 0)))
  
      gdb-filter-output))
  
--- 1975,1984 ----
  
      (setq gdb-output-sink 'user)
      ;; Remove padding.
!     (with-current-buffer gdb-accumulator
!       (goto-char (point-min))
!       (while (re-search-forward "^\n" nil t)
!     	(replace-match "")))
  
      gdb-filter-output))