]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/vlf/vlf-tune.el
* packages/vlf: Version 1.7
[gnu-emacs-elpa] / packages / vlf / vlf-tune.el
index adf84687eec941ad3a79ba71a70b975746c93c40..71e3d5fce7eaee0c9ae784253bd94ab6d765f1e8 100644 (file)
@@ -56,15 +56,18 @@ but don't change batch size.  If t, measure and change."
             (* 1000 (string-to-number (substring free match-from
                                                  (match-end 0))))))))
 
-(defcustom vlf-tune-max (let ((ram-size (vlf-tune-ram-size)))
-                          (if ram-size
-                              (/ ram-size 20)
-                            large-file-warning-threshold))
-  "Maximum batch size in bytes when auto tuning."
+(defcustom vlf-tune-max (max (let ((ram-size (vlf-tune-ram-size)))
+                               (if ram-size
+                                   (/ ram-size 20)
+                                 0))
+                             large-file-warning-threshold)
+  "Maximum batch size in bytes when auto tuning.
+Avoid increasing this after opening file with VLF."
   :group 'vlf :type 'integer)
 
-(defcustom vlf-tune-step (/ vlf-tune-max 1000)
-  "Step used for tuning in bytes."
+(defcustom vlf-tune-step (/ vlf-tune-max 10000)
+  "Step used for tuning in bytes.
+Avoid decreasing this after opening file with VLF."
   :group 'vlf :type 'integer)
 
 (defcustom vlf-tune-load-time 1.0
@@ -88,18 +91,35 @@ but don't change batch size.  If t, measure and change."
 
 (defvar vlf-tune-write-bps nil
   "Vector of bytes per second write measurements.")
-(make-variable-buffer-local 'vlf-tune-write-bps)
-(put 'vlf-tune-write-bps 'permanent-local t)
 
 (defvar vlf-tune-hexl-bps nil
   "Vector of bytes per second hexlify measurements.")
-(make-variable-buffer-local 'vlf-tune-hexl-bps)
-(put 'vlf-tune-hexl-bps 'permanent-local t)
 
 (defvar vlf-tune-dehexlify-bps nil
   "Vector of bytes per second dehexlify measurements.")
-(make-variable-buffer-local 'vlf-tune-dehexlify-bps)
-(put 'vlf-tune-dehexlify-bps 'permanent-local t)
+
+(defvar vlf-start-pos)
+(defvar hexl-bits)
+(defvar hexl-max-address)
+(declare-function hexl-line-displen "hexl")
+(declare-function dehexlify-buffer "hexl")
+
+(defun vlf-tune-copy-profile (from-buffer &optional to-buffer)
+  "Copy specific profile vectors of FROM-BUFFER to TO-BUFFER.
+If TO-BUFFER is nil, copy to current buffer."
+  (let (insert-bps insert-raw-bps encode-bps)
+    (with-current-buffer from-buffer
+      (setq insert-bps vlf-tune-insert-bps
+            insert-raw-bps vlf-tune-insert-raw-bps
+            encode-bps vlf-tune-encode-bps))
+    (if to-buffer
+        (with-current-buffer to-buffer
+          (setq vlf-tune-insert-bps insert-bps
+                vlf-tune-insert-raw-bps insert-raw-bps
+                vlf-tune-encode-bps encode-bps))
+      (setq vlf-tune-insert-bps insert-bps
+            vlf-tune-insert-raw-bps insert-raw-bps
+            vlf-tune-encode-bps encode-bps))))
 
 (defun vlf-tune-closest-index (size)
   "Get closest measurement index corresponding to SIZE."
@@ -111,9 +131,7 @@ but don't change batch size.  If t, measure and change."
 
 (defun vlf-tune-initialize-measurement ()
   "Initialize measurement vector."
-  (make-local-variable 'vlf-tune-max)
-  (make-local-variable 'vlf-tune-step)
-  (make-vector (/ vlf-tune-max vlf-tune-step) nil))
+  (make-vector (1- (/ vlf-tune-max vlf-tune-step)) nil))
 
 (defmacro vlf-tune-add-measurement (vec size time)
   "Add at an appropriate position in VEC new SIZE TIME measurement.
@@ -147,10 +165,11 @@ VEC is a vector of (mean time . count) elements ordered by size."
                               (- end start) (car result))
     (cdr result)))
 
-(defun vlf-tune-insert-file-contents-literally (start end)
-  "Insert raw file bytes START to END and save time it takes."
+(defun vlf-tune-insert-file-contents-literally (start end &optional file)
+  "Insert raw file bytes START to END and save time it takes.
+FILE if given is filename to be used, otherwise `buffer-file-name'."
   (let ((result (vlf-time (insert-file-contents-literally
-                           buffer-file-name nil start end))))
+                           (or file buffer-file-name) nil start end))))
     (vlf-tune-add-measurement vlf-tune-insert-raw-bps
                               (- end start) (car result))
     (cdr result)))
@@ -164,27 +183,44 @@ VEC is a vector of (mean time . count) elements ordered by size."
                               (cdr result) (car result))
     (cdr result)))
 
-(defun vlf-tune-write (start end append visit size)
+(defun vlf-tune-write (start end append visit size &optional file-name)
   "Save buffer and save time it takes.
 START, END, APPEND, VISIT have same meaning as in `write-region'.
-SIZE is number of bytes that are saved."
-  (let ((time (car (vlf-time (write-region start end buffer-file-name
-                                           append visit)))))
-    (vlf-tune-add-measurement vlf-tune-write-bps size time)))
+SIZE is number of bytes that are saved.
+FILE-NAME if given is to be used instead of `buffer-file-name'."
+  (let* ((file (or file-name buffer-file-name))
+         (time (car (vlf-time (write-region start end file append
+                                            visit)))))
+    (or (file-remote-p file) ;writing to remote files can include network copying
+        (vlf-tune-add-measurement vlf-tune-write-bps size time))))
+
+(defun vlf-hexl-adjust-addresses ()
+  "Adjust hexl address indicators according to `vlf-start-pos'."
+  (let ((pos (point))
+        (address vlf-start-pos))
+    (goto-char (point-min))
+    (while (re-search-forward "^[[:xdigit:]]+" nil t)
+      (replace-match (format "%08x" address))
+      (setq address (+ address hexl-bits)))
+    (goto-char pos)))
 
 (defun vlf-tune-hexlify ()
   "Activate `hexl-mode' and save time it takes."
-  (or (derived-mode-p 'hexl-mode)
-      (let ((time (car (vlf-time (hexl-mode)))))
+  (let* ((no-adjust (zerop vlf-start-pos))
+         (time (car (vlf-time (hexlify-buffer)
+                              (or no-adjust
+                                  (vlf-hexl-adjust-addresses))))))
+    (setq hexl-max-address (+ (* (/ (1- (buffer-size))
+                                    (hexl-line-displen)) 16) 15))
+    (or no-adjust
         (vlf-tune-add-measurement vlf-tune-hexl-bps
                                   hexl-max-address time))))
 
 (defun vlf-tune-dehexlify ()
   "Exit `hexl-mode' and save time it takes."
-  (if (derived-mode-p 'hexl-mode)
-      (let ((time (car (vlf-time (hexl-mode-exit)))))
-        (vlf-tune-add-measurement vlf-tune-dehexlify-bps
-                                  hexl-max-address time))))
+  (let ((time (car (vlf-time (dehexlify-buffer)))))
+    (vlf-tune-add-measurement vlf-tune-dehexlify-bps
+                              hexl-max-address time)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; tuning
@@ -233,7 +269,8 @@ unless DONT-APPROXIMATE is t."
                      `(aset ,vec ,index
                             (vlf-tune-approximate-nearby ,vec ,index))
                    `(vlf-tune-approximate-nearby ,vec ,index)))
-               (t val)))))
+               (t val)))
+     most-positive-fixnum))
 
 (defmacro vlf-tune-get-vector (key)
   "Get vlf-tune vector corresponding to KEY."
@@ -268,7 +305,7 @@ If it is number, stop as soon as cumulative time gets equal or above."
         (let ((bps (if (consp el)
                        (vlf-tune-assess (car el) (cadr el) index
                                         approximate)
-                     (vlf-tune-assess el 1 index approximate))))
+                     (vlf-tune-assess el 1.0 index approximate))))
           (if (zerop bps)
               (throw 'result nil)
             (setq time (+ time (/ size bps)))
@@ -332,55 +369,57 @@ MIN and MAX specify interval of indexes to search."
           (setq vlf-batch-size (* (1+ left-idx) vlf-tune-step)))))))
 
 (defun vlf-tune-linear (types max-idx)
-  "Adjust `vlf-batch-size' to optimal value using linear search, \
-optimizing over TYPES up to MAX-IDX."
+  "Adjust `vlf-batch-size' to optimal known value using linear search.
+Optimize over TYPES up to MAX-IDX."
   (let ((best-idx 0)
         (best-bps 0)
-        (idx 0)
-        (none-missing t))
-    (while (and none-missing (< idx max-idx))
-      (let ((bps (vlf-tune-score types idx)))
-        (cond ((null bps)
-               (setq vlf-batch-size (* (1+ idx) vlf-tune-step)
-                     none-missing nil))
-              ((< best-bps bps) (setq best-idx idx
-                                      best-bps bps))))
+        (idx 0))
+    (while (< idx max-idx)
+      (let ((bps (vlf-tune-score types idx t)))
+        (and bps (< best-bps bps)
+             (setq best-idx idx
+                   best-bps bps)))
       (setq idx (1+ idx)))
-    (or (not none-missing)
-        (setq vlf-batch-size (* (1+ best-idx) vlf-tune-step)))))
+    (setq vlf-batch-size (* (1+ best-idx) vlf-tune-step))))
 
-(defun vlf-tune-batch (types &optional linear)
+(defun vlf-tune-batch (types &optional linear file)
   "Adjust `vlf-batch-size' to optimal value optimizing on TYPES.
 TYPES is alist of elements that may be of form (type coef) or
 non list values in which case coeficient is assumed 1.
 Types can be :insert, :raw, :encode, :write, :hexl or :dehexlify.
 If LINEAR is non nil, use brute-force.  In case requested measurement
 is missing, stop search and set `vlf-batch-size' to this value.
+FILE if given is filename to be used, otherwise `buffer-file-name'.
 Suitable for multiple batch operations."
   (if (eq vlf-tune-enabled t)
       (let ((max-idx (1- (/ (min vlf-tune-max
                                  (/ (1+ vlf-file-size) 2))
                             vlf-tune-step))))
-        (cond (linear (vlf-tune-linear types max-idx))
-              ((file-remote-p buffer-file-name)
-               (vlf-tune-conservative types))
-              ((<= 1 max-idx)
-               (if (< max-idx 3)
-                   (vlf-tune-conservative types (/ max-idx 2))
-                 (vlf-tune-binary types 0 max-idx)))))))
+        (if linear
+            (vlf-tune-linear types max-idx)
+          (let ((batch-size vlf-batch-size))
+            (cond ((file-remote-p (or file buffer-file-name))
+                   (vlf-tune-conservative types))
+                  ((<= 1 max-idx)
+                   (if (< max-idx 3)
+                       (vlf-tune-conservative types (/ max-idx 2))
+                     (vlf-tune-binary types 0 max-idx))))
+            (if (= batch-size vlf-batch-size) ;local maxima?
+                (vlf-tune-linear types max-idx)))))))
 
 (defun vlf-tune-optimal-load (types &optional min-idx max-idx)
   "Get best batch size according to existing measurements over TYPES.
 Best considered where primitive operations total is closest to
 `vlf-tune-load-time'.  If MIN-IDX and MAX-IDX are given,
 confine search to this region."
-  (if vlf-tune-enabled
+  (if (eq vlf-tune-enabled t)
       (progn
-        (setq max-idx (min (or max-idx vlf-tune-max)
+        (setq min-idx (max 0 (or min-idx 0))
+              max-idx (min (or max-idx vlf-tune-max)
                            (1- (/ (min vlf-tune-max
                                        (/ (1+ vlf-file-size) 2))
                                   vlf-tune-step))))
-        (let* ((idx (max 0 (or min-idx 0)))
+        (let* ((idx min-idx)
                (best-idx idx)
                (best-time-diff vlf-tune-load-time)
                (all-less t)