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


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.