बड़े बफ़र्स में `लाइन-नंबर-एट-पॉस` प्राप्त करने की एक तेज़ विधि


19

फ़ंक्शन line-number-at-pos(जब लगभग 50 बार दोहराया जाता है) अर्ध-बड़े बफ़र्स में ध्यान देने योग्य धीमा-नीचे का कारण बन रहा है - जैसे, 50,000 लाइनें - जब बिंदु बफर के अंत के पास होता है। धीमे-धीमे से मेरा मतलब कुल मिलाकर लगभग 1.35 सेकंड है।

elispकाउंट-लाइन्स और बफ़र के शीर्ष पर 100% फ़ंसीटॉन का उपयोग करने के बजाय , मैं एक हाइब्रिड विधि में दिलचस्पी लूंगा जो मोड-लाइन पर दिखाई देने वाली लाइन संख्या के लिए जिम्मेदार अंतर्निहित C क्षमताओं में टैप करता हो। मोड-लाइन पर दिखाई देने वाली लाइन-संख्या बफर के आकार की परवाह किए बिना, हल्की गति से होती है।


यहाँ एक परीक्षण समारोह है:

(defmacro measure-time (&rest body)
"Measure the time it takes to evaluate BODY.
http://lists.gnu.org/archive/html/help-gnu-emacs/2008-06/msg00087.html"
  `(let ((time (current-time)))
     ,@body
     (message "%.06f" (float-time (time-since time)))))

(measure-time
  (let* (
      line-numbers
      (window-start (window-start))
      (window-end (window-end)))
    (save-excursion
      (goto-char window-end)
      (while
        (re-search-backward "\n" window-start t)
        (push (line-number-at-pos) line-numbers)))
    line-numbers))

जवाबों:


17

प्रयत्न

(string-to-number (format-mode-line "%l"))

आप % का उपयोग करके अन्य जानकारी निकाल सकते हैं- Emacs Lisp Manual में वर्णित -Constructs

चेतावनी:

वासमासा और स्टीफन द्वारा उल्लिखित सीमाओं के अलावा (नीचे टिप्पणियां देखें) यह उन बफ़र्स के लिए काम नहीं करता है जो प्रदर्शित नहीं होते हैं।

इसे इस्तेमाल करे:

(with-temp-buffer
  (dotimes (i 10000)
    (insert (format "%d\n" i)))
  (string-to-number (format-mode-line "%l")))

और से तुलना करें

(with-temp-buffer
  (dotimes (i 10000)
    (insert (format "%d\n" i)))
  (line-number-at-pos))

हाँ, यह 1.35 सेकंड से घटकर 0.003559 हो गया है! बहुत बहुत धन्यवाद - बहुत सराहना की! :)
8

6
ध्यान रखें कि यह विधि आपको "??" लाइनों के लिए line-number-display-limit-widthजो डिफ़ॉल्ट रूप से 200 के मान पर सेट है जैसा कि मैंने यहां पाया ।
वामासा

3
IIRC का परिणाम अविश्वसनीय भी हो सकता है यदि पिछले रिडिसप्ले के बाद बफर में संशोधन हुए हैं।
स्टीफन

मेरा मानना ​​है कि उत्तर में परीक्षणों को संशोधित करना आवश्यक होगा जैसे कि दूसरे पत्र iको (string-to-number (format-mode-line "%l"))पहले परीक्षण के लिए बदल दिया जाता है , और दूसरे पत्र iको (line-number-at-pos)दूसरे परीक्षण के साथ बदल दिया जाता है ।
कानून

5

nlinum.el निम्नलिखित का उपयोग करता है:

(defvar nlinum--line-number-cache nil)
(make-variable-buffer-local 'nlinum--line-number-cache)

;; We could try and avoid flushing the cache at every change, e.g. with:
;;   (defun nlinum--before-change (start _end)
;;     (if (and nlinum--line-number-cache
;;              (< start (car nlinum--line-number-cache)))
;;         (save-excursion (goto-char start) (nlinum--line-number-at-pos))))
;; But it's far from clear that it's worth the trouble.  The current simplistic
;; approach seems to be good enough in practice.

(defun nlinum--after-change (&rest _args)
  (setq nlinum--line-number-cache nil))

(defun nlinum--line-number-at-pos ()
  "Like `line-number-at-pos' but sped up with a cache."
  ;; (assert (bolp))
  (let ((pos
         (if (and nlinum--line-number-cache
                  (> (- (point) (point-min))
                     (abs (- (point) (car nlinum--line-number-cache)))))
             (funcall (if (> (point) (car nlinum--line-number-cache))
                          #'+ #'-)
                      (cdr nlinum--line-number-cache)
                      (count-lines (point) (car nlinum--line-number-cache)))
           (line-number-at-pos))))
    ;;(assert (= pos (line-number-at-pos)))
    (setq nlinum--line-number-cache (cons (point) pos))
    pos))

मोड फ़ंक्शन में निम्न अतिरिक्त कॉन्फ़िगरेशन के साथ:

(add-hook 'after-change-functions #'nlinum--after-change nil t)

1
आह ... मैं आज सुबह ही आपके पुस्तकालय के बारे में सोच रहा था। line-number-at-posConstantine द्वारा जवाब के साथ प्रतिस्थापित किया जा सकता है, और वह भी अधिक यह की तुलना में पहले से ही अपने अपने पुस्तकालय में तेजी लाने होगा - विशेष रूप से बड़े बफ़र्स में। count-linesकॉन्स्टेंटाइन द्वारा विधि का उपयोग करके भी तय किया जाना चाहिए। मैं उन कार्यों को ठीक करने के लिए रिपोर्ट-एमएसीएस-बग हॉटलाइन पर एक सुझाव-बॉक्स प्रस्तुत करने के बारे में सोच रहा था।
कानून
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.