test: verify Flex resize through public Ebox reports
This commit is contained in:
parent
94bac1c7c7
commit
81957acdf3
32
Makefile
32
Makefile
@ -2,26 +2,48 @@ EMACS ?= emacs
|
|||||||
ECSS_DIR ?= ../ecss
|
ECSS_DIR ?= ../ecss
|
||||||
TP_DIR ?= ../tp
|
TP_DIR ?= ../tp
|
||||||
LOAD_PATH = -L . -L ../ebox -L $(ECSS_DIR) -L $(TP_DIR)
|
LOAD_PATH = -L . -L ../ebox -L $(ECSS_DIR) -L $(TP_DIR)
|
||||||
|
EBOX_NATIVE_RELEASE_DIR = $(shell $(EMACS) -Q --batch $(LOAD_PATH) \
|
||||||
|
--eval '(setq native-comp-jit-compilation nil)' \
|
||||||
|
-l ../ebox/ebox-native-reflow.el \
|
||||||
|
--eval '(princ (expand-file-name (format "../ebox/native/target/%s/release/" (ebox-native-reflow--rust-target))))')
|
||||||
|
|
||||||
.PHONY: all compile test check checkdoc load performance-evaluator clean
|
.PHONY: all compile test check checkdoc load performance performance-prepare \
|
||||||
|
performance-evaluator clean
|
||||||
|
|
||||||
all: check
|
all: check
|
||||||
|
|
||||||
compile:
|
compile:
|
||||||
rm -f *.elc tests/*.elc
|
rm -f *.elc tests/*.elc
|
||||||
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(setq load-prefer-newer t)' \
|
$(EMACS) -Q --batch $(LOAD_PATH) \
|
||||||
|
--eval '(setq load-prefer-newer t native-comp-jit-compilation nil byte-compile-error-on-warn t)' \
|
||||||
--eval '(load-file "ebox-playground.el")' \
|
--eval '(load-file "ebox-playground.el")' \
|
||||||
--eval '(byte-compile-file "ebox-playground.el")'
|
--eval '(byte-compile-file "ebox-playground.el")' \
|
||||||
|
--eval '(byte-compile-file "scripts/ebox-playground-flex-resize-evaluator.el")'
|
||||||
|
|
||||||
test: compile
|
test: compile
|
||||||
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(setq load-prefer-newer t)' \
|
$(EMACS) -Q --batch $(LOAD_PATH) \
|
||||||
|
--eval '(setq load-prefer-newer t native-comp-jit-compilation nil)' \
|
||||||
-l tests/ebox-playground-tests.el -f ert-run-tests-batch-and-exit
|
-l tests/ebox-playground-tests.el -f ert-run-tests-batch-and-exit
|
||||||
|
|
||||||
load: compile
|
load: compile
|
||||||
$(EMACS) -Q --batch $(LOAD_PATH) --eval '(require (quote ebox-playground))' \
|
$(EMACS) -Q --batch $(LOAD_PATH) \
|
||||||
|
--eval '(setq native-comp-jit-compilation nil)' \
|
||||||
|
--eval '(require (quote ebox-playground))' \
|
||||||
--eval '(princ "ebox-playground load OK\n")'
|
--eval '(princ "ebox-playground load OK\n")'
|
||||||
|
|
||||||
|
performance:
|
||||||
|
$(MAKE) performance-prepare EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
|
||||||
|
$(MAKE) performance-evaluator EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
|
||||||
|
|
||||||
|
performance-prepare:
|
||||||
|
$(MAKE) -C $(ECSS_DIR) compile EMACS="$(EMACS)"
|
||||||
|
$(MAKE) -C $(TP_DIR) compile EMACS="$(EMACS)"
|
||||||
|
$(MAKE) -C ../ebox compile EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
|
||||||
|
$(MAKE) compile EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
|
||||||
|
$(MAKE) -C ../ebox native-build EMACS="$(EMACS)" ECSS_DIR="$(ECSS_DIR)" TP_DIR="$(TP_DIR)"
|
||||||
|
|
||||||
performance-evaluator:
|
performance-evaluator:
|
||||||
|
EBOX_NATIVE_REFLOW_MODULE_PATH="$(EBOX_NATIVE_RELEASE_DIR)" \
|
||||||
EMACS="$(EMACS)" ./scripts/flex-resize-evaluator.sh
|
EMACS="$(EMACS)" ./scripts/flex-resize-evaluator.sh
|
||||||
|
|
||||||
checkdoc:
|
checkdoc:
|
||||||
|
|||||||
@ -28,3 +28,12 @@ The reference fixtures live directly under `examples/`. For example:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory.
|
Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory.
|
||||||
|
|
||||||
|
Run `make performance` for the committed Flex resize gate. It prepares ECSS,
|
||||||
|
TP, Ebox, Playground bytecode, and the Rust module, then renders a read-only
|
||||||
|
`HEAD:examples/flex-reference.ebox` snapshot without touching the working-tree
|
||||||
|
fixture. The GUI driver performs five warmups followed by 30 accepted viewport
|
||||||
|
updates; requested and published widths must match exactly, and both p95 and max
|
||||||
|
must remain at or below 50ms. For uncontaminated repeated samples, run
|
||||||
|
`make performance-prepare`, let compilation activity settle, then run
|
||||||
|
`make performance-evaluator` without rebuilding.
|
||||||
|
|||||||
@ -13,14 +13,21 @@
|
|||||||
|
|
||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
(require 'ebox-playground)
|
(require 'ebox-playground)
|
||||||
|
(require 'ebox-native-reflow)
|
||||||
|
|
||||||
(defconst ebox-playground-flex-resize-evaluator--fixture
|
(defcustom ebox-playground-flex-resize-evaluator-fixture
|
||||||
|
(or (getenv "EBOX_PLAYGROUND_FLEX_FIXTURE")
|
||||||
(expand-file-name "examples/flex-reference.ebox"
|
(expand-file-name "examples/flex-reference.ebox"
|
||||||
ebox-playground-directory)
|
ebox-playground-directory))
|
||||||
"Flex fixture used by the performance evaluator.")
|
"Read-only Flex fixture used by the performance evaluator."
|
||||||
|
:type 'file
|
||||||
|
:group 'ebox-playground)
|
||||||
|
|
||||||
(defcustom ebox-playground-flex-resize-evaluator-max-seconds 0.5
|
(defconst ebox-playground-flex-resize-evaluator-warmup-count 5)
|
||||||
"Maximum allowed end-to-end time for one settled preview resize."
|
(defconst ebox-playground-flex-resize-evaluator-sample-count 30)
|
||||||
|
|
||||||
|
(defcustom ebox-playground-flex-resize-evaluator-max-seconds 2.0
|
||||||
|
"Maximum allowed end-to-end time for the measured resize burst."
|
||||||
:type 'number
|
:type 'number
|
||||||
:group 'ebox-playground)
|
:group 'ebox-playground)
|
||||||
|
|
||||||
@ -37,18 +44,21 @@
|
|||||||
(defvar ebox-playground-flex-resize-evaluator--output-lines nil
|
(defvar ebox-playground-flex-resize-evaluator--output-lines nil
|
||||||
"Report lines collected during one evaluator run.")
|
"Report lines collected during one evaluator run.")
|
||||||
|
|
||||||
|
(defun ebox-playground-flex-resize-evaluator--percentile
|
||||||
|
(samples percentile)
|
||||||
|
"Return nearest-rank PERCENTILE from numeric SAMPLES."
|
||||||
|
(unless samples
|
||||||
|
(error "Flex evaluator cannot summarize empty samples"))
|
||||||
|
(let* ((ordered (sort (copy-sequence samples) #'<))
|
||||||
|
(rank (max 1 (ceiling (* percentile (length ordered))))))
|
||||||
|
(nth (1- rank) ordered)))
|
||||||
|
|
||||||
(defconst ebox-playground-flex-resize-evaluator--runtime-properties
|
(defconst ebox-playground-flex-resize-evaluator--runtime-properties
|
||||||
(delete-dups
|
(delete-dups
|
||||||
(append (mapcar #'cdr ebox-region-types)
|
(append (mapcar #'cdr ebox-region-types)
|
||||||
'(ebox-content-idx ebox-content-owners ebox-scroll-window)))
|
'(ebox-content-idx ebox-content-owners ebox-scroll-window)))
|
||||||
"Ebox identity properties omitted from fresh-render comparison.")
|
"Ebox identity properties omitted from fresh-render comparison.")
|
||||||
|
|
||||||
(defun ebox-playground-flex-resize-evaluator--preview-buffer ()
|
|
||||||
"Return the preview buffer for the fixed flex fixture."
|
|
||||||
(get-buffer
|
|
||||||
(format "*Ebox Preview: %s*"
|
|
||||||
ebox-playground-flex-resize-evaluator--fixture)))
|
|
||||||
|
|
||||||
(defun ebox-playground-flex-resize-evaluator--line-widths (buffer)
|
(defun ebox-playground-flex-resize-evaluator--line-widths (buffer)
|
||||||
"Return pixel widths for every rendered line in BUFFER."
|
"Return pixel widths for every rendered line in BUFFER."
|
||||||
(with-current-buffer buffer
|
(with-current-buffer buffer
|
||||||
@ -84,9 +94,10 @@ mounted the split. This setup publication is outside the measured splitter
|
|||||||
action, so the action starts from a self-consistent runtime generation rather
|
action, so the action starts from a self-consistent runtime generation rather
|
||||||
than charging initial frame settling to resize."
|
than charging initial frame settling to resize."
|
||||||
(let* ((width (ebox-playground--window-viewport-width preview-window))
|
(let* ((width (ebox-playground--window-viewport-width preview-window))
|
||||||
(state (and (buffer-live-p preview)
|
(report (ebox-buffer-update-report preview))
|
||||||
(ebox--buffer-render-state preview)))
|
(published-width (and report
|
||||||
(published-width (and state (plist-get state :viewport-width))))
|
(or (plist-get report :target-viewport-width)
|
||||||
|
(plist-get report :viewport-width)))))
|
||||||
(unless (numberp width)
|
(unless (numberp width)
|
||||||
(error "flex preview has no settled viewport width"))
|
(error "flex preview has no settled viewport width"))
|
||||||
(when (not (equal width published-width))
|
(when (not (equal width published-width))
|
||||||
@ -109,26 +120,37 @@ concurrent cache warming CPU work."
|
|||||||
(source nil)
|
(source nil)
|
||||||
(preview nil)
|
(preview nil)
|
||||||
(preview-window nil)
|
(preview-window nil)
|
||||||
(resize-advice nil)
|
(warmup-publications 0)
|
||||||
(resize-count 0)
|
(resize-count 0)
|
||||||
(resize-elapsed 0.0)
|
|
||||||
(resize-finished nil)
|
(resize-finished nil)
|
||||||
(action-start nil)
|
(action-start nil)
|
||||||
(last-event-elapsed nil)
|
(last-event-elapsed nil)
|
||||||
(resize-publications nil)
|
(resize-publications nil)
|
||||||
(resize-durations nil)
|
(publication-durations nil)
|
||||||
|
(requested-widths nil)
|
||||||
|
(accepted-widths nil)
|
||||||
|
(observer nil)
|
||||||
|
(native-report nil)
|
||||||
|
(playground-library (symbol-file 'ebox-playground-open 'defun))
|
||||||
|
(evaluator-library
|
||||||
|
(symbol-file 'ebox-playground-flex-resize-evaluator-run 'defun))
|
||||||
(completed-without-error nil)
|
(completed-without-error nil)
|
||||||
(ebox-playground-flex-resize-evaluator--output-lines nil)
|
(ebox-playground-flex-resize-evaluator--output-lines nil)
|
||||||
(checks nil))
|
(checks nil))
|
||||||
(condition-case-unless-debug error-data
|
(condition-case-unless-debug error-data
|
||||||
(progn
|
(progn
|
||||||
(delete-other-windows)
|
(delete-other-windows)
|
||||||
|
(setq native-report (ebox-native-reflow-runtime-report))
|
||||||
|
(unless (plist-get native-report :layout-ready-p)
|
||||||
|
(error "Flex evaluator requires the prepared native layout module"))
|
||||||
|
(unless (file-readable-p
|
||||||
|
ebox-playground-flex-resize-evaluator-fixture)
|
||||||
|
(error "Flex evaluator fixture is not readable: %s"
|
||||||
|
ebox-playground-flex-resize-evaluator-fixture))
|
||||||
(setq source
|
(setq source
|
||||||
(find-file ebox-playground-flex-resize-evaluator--fixture))
|
(find-file ebox-playground-flex-resize-evaluator-fixture))
|
||||||
(ebox-dsl-mode)
|
(ebox-dsl-mode)
|
||||||
(ebox-dsl-render)
|
(setq preview (ebox-dsl-render)
|
||||||
(setq preview
|
|
||||||
(ebox-playground-flex-resize-evaluator--preview-buffer)
|
|
||||||
preview-window (get-buffer-window preview (selected-frame)))
|
preview-window (get-buffer-window preview (selected-frame)))
|
||||||
(unless (and (buffer-live-p preview)
|
(unless (and (buffer-live-p preview)
|
||||||
(window-live-p preview-window))
|
(window-live-p preview-window))
|
||||||
@ -139,30 +161,52 @@ concurrent cache warming CPU work."
|
|||||||
preview preview-window)
|
preview preview-window)
|
||||||
(redisplay t)
|
(redisplay t)
|
||||||
(sleep-for 0.2)
|
(sleep-for 0.2)
|
||||||
(setq resize-advice
|
;; Observe only accepted, completed Ebox publications. TP emits its
|
||||||
(lambda (original &rest arguments)
|
;; paired report first; filtering by provider keeps this evaluator on
|
||||||
(setq resize-count (1+ resize-count))
|
;; the public Ebox boundary and avoids timing/advising the rerender
|
||||||
(let ((start (float-time)))
|
;; implementation itself.
|
||||||
(unwind-protect
|
(setq observer
|
||||||
(apply original arguments)
|
(lambda (_buffer report)
|
||||||
(let ((duration (- (float-time) start)))
|
(when (and (eq (plist-get report :provider) 'ebox)
|
||||||
(setq resize-elapsed (+ resize-elapsed duration))
|
(eq (plist-get report :stage) 'viewport))
|
||||||
(push duration resize-durations))
|
(setq resize-count (1+ resize-count)
|
||||||
|
resize-finished t)
|
||||||
(when action-start
|
(when action-start
|
||||||
(push (- (float-time) action-start)
|
(push (- (float-time) action-start)
|
||||||
resize-publications))
|
resize-publications))
|
||||||
(setq resize-finished t)))))
|
(push (/ (or (plist-get report :duration-ms) 0.0)
|
||||||
(advice-add 'ebox-rerender-buffer-with-context
|
1000.0)
|
||||||
:around resize-advice)
|
publication-durations)
|
||||||
|
(push (or (plist-get report :target-viewport-width)
|
||||||
|
(plist-get report :viewport-width))
|
||||||
|
accepted-widths))))
|
||||||
|
(ebox-buffer-set-observer preview observer)
|
||||||
|
(dotimes (index ebox-playground-flex-resize-evaluator-warmup-count)
|
||||||
|
(window-resize preview-window (if (zerop (% index 2)) -1 1) t)
|
||||||
|
(redisplay t)
|
||||||
|
(sleep-for 0.01))
|
||||||
|
(setq warmup-publications resize-count
|
||||||
|
resize-count 0
|
||||||
|
resize-finished nil
|
||||||
|
resize-publications nil
|
||||||
|
publication-durations nil
|
||||||
|
requested-widths nil
|
||||||
|
accepted-widths nil)
|
||||||
(let* ((start (float-time))
|
(let* ((start (float-time))
|
||||||
(old-width
|
(old-width
|
||||||
(ebox-playground--window-viewport-width preview-window)))
|
(ebox-playground--window-viewport-width preview-window)))
|
||||||
(setq action-start start)
|
(setq action-start start)
|
||||||
(dolist (delta '(-4 2 -4 2 -4 2))
|
(dotimes (index ebox-playground-flex-resize-evaluator-sample-count)
|
||||||
|
(let ((delta
|
||||||
|
(if (< index 28)
|
||||||
|
(if (zerop (% index 2)) -1 1)
|
||||||
|
-1)))
|
||||||
(setq last-event-elapsed (- (float-time) start))
|
(setq last-event-elapsed (- (float-time) start))
|
||||||
(window-resize preview-window delta t)
|
(window-resize preview-window delta t)
|
||||||
|
(push (ebox-playground--window-viewport-width preview-window)
|
||||||
|
requested-widths)
|
||||||
(redisplay t)
|
(redisplay t)
|
||||||
(sleep-for 0.02))
|
(sleep-for 0.01)))
|
||||||
(let* ((elapsed (- (float-time) start))
|
(let* ((elapsed (- (float-time) start))
|
||||||
(publication-times
|
(publication-times
|
||||||
(sort (copy-sequence resize-publications) #'<))
|
(sort (copy-sequence resize-publications) #'<))
|
||||||
@ -173,7 +217,14 @@ concurrent cache warming CPU work."
|
|||||||
(first-publication (car publication-times))
|
(first-publication (car publication-times))
|
||||||
(last-publication (car (last publication-times)))
|
(last-publication (car (last publication-times)))
|
||||||
(max-publication
|
(max-publication
|
||||||
(if resize-durations (apply #'max resize-durations) 0.0))
|
(if publication-durations
|
||||||
|
(apply #'max publication-durations)
|
||||||
|
0.0))
|
||||||
|
(p95-publication
|
||||||
|
(if publication-durations
|
||||||
|
(ebox-playground-flex-resize-evaluator--percentile
|
||||||
|
publication-durations 0.95)
|
||||||
|
0.0))
|
||||||
(max-gap
|
(max-gap
|
||||||
(if publication-gaps (apply #'max publication-gaps) 0.0))
|
(if publication-gaps (apply #'max publication-gaps) 0.0))
|
||||||
(final-latency
|
(final-latency
|
||||||
@ -183,10 +234,8 @@ concurrent cache warming CPU work."
|
|||||||
(ebox-playground--window-viewport-width preview-window))
|
(ebox-playground--window-viewport-width preview-window))
|
||||||
(report (ebox-buffer-update-report preview))
|
(report (ebox-buffer-update-report preview))
|
||||||
(projection-kind (plist-get report :projection-kind))
|
(projection-kind (plist-get report :projection-kind))
|
||||||
(native-flex-calls
|
(expected-widths (nreverse requested-widths))
|
||||||
(and (boundp
|
(published-widths (nreverse accepted-widths))
|
||||||
'ebox-native-reflow--flex-geometry-call-count)
|
|
||||||
ebox-native-reflow--flex-geometry-call-count))
|
|
||||||
(line-widths
|
(line-widths
|
||||||
(ebox-playground-flex-resize-evaluator--line-widths
|
(ebox-playground-flex-resize-evaluator--line-widths
|
||||||
preview))
|
preview))
|
||||||
@ -202,16 +251,14 @@ concurrent cache warming CPU work."
|
|||||||
;; Compare the published visible scroll
|
;; Compare the published visible scroll
|
||||||
;; window with a fresh render at the same
|
;; window with a fresh render at the same
|
||||||
;; viewport height. Omitting this binding
|
;; viewport height. Omitting this binding
|
||||||
;; rendered the entire lazy document and made
|
|
||||||
;; every correct retained resize look unequal.
|
|
||||||
(ebox-viewport-height
|
(ebox-viewport-height
|
||||||
(or (plist-get
|
(or (plist-get report
|
||||||
(ebox--buffer-render-state preview)
|
:target-viewport-height)
|
||||||
:viewport-height)
|
(plist-get report :viewport-height)
|
||||||
36)))
|
36)))
|
||||||
(ebox-render
|
(ebox-render
|
||||||
(ebox-playground-view
|
(ebox-playground-view
|
||||||
ebox-playground-flex-resize-evaluator--fixture
|
ebox-playground-flex-resize-evaluator-fixture
|
||||||
viewport-width)))))
|
viewport-width)))))
|
||||||
(fresh-render-matches-p
|
(fresh-render-matches-p
|
||||||
(and (stringp fresh-rendered)
|
(and (stringp fresh-rendered)
|
||||||
@ -230,24 +277,55 @@ concurrent cache warming CPU work."
|
|||||||
(not (plist-get report :tp-scope-fallback)))))
|
(not (plist-get report :tp-scope-fallback)))))
|
||||||
(setq checks
|
(setq checks
|
||||||
(list
|
(list
|
||||||
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
|
"compiled evaluator artifacts"
|
||||||
|
(and (stringp playground-library)
|
||||||
|
(string-suffix-p ".elc" playground-library)
|
||||||
|
(stringp evaluator-library)
|
||||||
|
(string-suffix-p ".elc" evaluator-library))
|
||||||
|
(format "playground=%S evaluator=%S"
|
||||||
|
playground-library evaluator-library))
|
||||||
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
|
"native module prepared"
|
||||||
|
(plist-get native-report :layout-ready-p)
|
||||||
|
(format "path=%S hash=%S"
|
||||||
|
(plist-get native-report :loaded-module-path)
|
||||||
|
(plist-get native-report :loaded-module-hash)))
|
||||||
(ebox-playground-flex-resize-evaluator--check
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
"preview mounted"
|
"preview mounted"
|
||||||
(and (buffer-live-p preview)
|
(and (buffer-live-p preview)
|
||||||
(window-live-p preview-window))
|
(window-live-p preview-window))
|
||||||
(format "source=%S preview=%S" source preview))
|
(format "source=%S preview=%S" source preview))
|
||||||
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
|
"warmup publications"
|
||||||
|
(= warmup-publications
|
||||||
|
ebox-playground-flex-resize-evaluator-warmup-count)
|
||||||
|
(format "warmups=%d expected=%d"
|
||||||
|
warmup-publications
|
||||||
|
ebox-playground-flex-resize-evaluator-warmup-count))
|
||||||
(ebox-playground-flex-resize-evaluator--check
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
"intermediate resize updates"
|
"intermediate resize updates"
|
||||||
(and (>= resize-count 4)
|
(and (= resize-count
|
||||||
|
ebox-playground-flex-resize-evaluator-sample-count)
|
||||||
|
(= resize-count (length expected-widths))
|
||||||
first-publication
|
first-publication
|
||||||
(<= first-publication
|
(<= first-publication
|
||||||
ebox-playground-flex-resize-evaluator-max-update-seconds)
|
ebox-playground-flex-resize-evaluator-max-update-seconds)
|
||||||
(< first-publication last-event-elapsed))
|
(< first-publication last-event-elapsed))
|
||||||
(format "updates=%d first=%.6fs last-event=%.6fs"
|
(format "updates=%d samples=%d first=%.6fs last-event=%.6fs"
|
||||||
resize-count
|
resize-count
|
||||||
|
ebox-playground-flex-resize-evaluator-sample-count
|
||||||
(or first-publication 0.0)
|
(or first-publication 0.0)
|
||||||
last-event-elapsed))
|
last-event-elapsed))
|
||||||
(ebox-playground-flex-resize-evaluator--check
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
"per-update resize budget"
|
"per-update p95 budget"
|
||||||
|
(<= p95-publication
|
||||||
|
ebox-playground-flex-resize-evaluator-max-update-seconds)
|
||||||
|
(format "p95=%.6fs threshold=%.6fs"
|
||||||
|
p95-publication
|
||||||
|
ebox-playground-flex-resize-evaluator-max-update-seconds))
|
||||||
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
|
"per-update max budget"
|
||||||
(<= max-publication
|
(<= max-publication
|
||||||
ebox-playground-flex-resize-evaluator-max-update-seconds)
|
ebox-playground-flex-resize-evaluator-max-update-seconds)
|
||||||
(format "max=%.6fs threshold=%.6fs"
|
(format "max=%.6fs threshold=%.6fs"
|
||||||
@ -277,11 +355,15 @@ concurrent cache warming CPU work."
|
|||||||
"viewport was published"
|
"viewport was published"
|
||||||
(and (numberp viewport-width)
|
(and (numberp viewport-width)
|
||||||
(not (equal old-width viewport-width))
|
(not (equal old-width viewport-width))
|
||||||
|
(cl-every #'numberp published-widths)
|
||||||
|
(equal expected-widths published-widths)
|
||||||
|
(equal viewport-width (car (last published-widths)))
|
||||||
(eq (plist-get report :constraint-source)
|
(eq (plist-get report :constraint-source)
|
||||||
'viewport)
|
'viewport)
|
||||||
(plist-get report :runtime-published))
|
(plist-get report :runtime-published))
|
||||||
(format "viewport=%S strategy=%S"
|
(format "viewport=%S expected=%S accepted=%S strategy=%S"
|
||||||
viewport-width (plist-get report :strategy)))
|
viewport-width expected-widths published-widths
|
||||||
|
(plist-get report :strategy)))
|
||||||
(ebox-playground-flex-resize-evaluator--check
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
"retained viewport projection"
|
"retained viewport projection"
|
||||||
projection-retained-p
|
projection-retained-p
|
||||||
@ -304,21 +386,22 @@ concurrent cache warming CPU work."
|
|||||||
'((default (:background "#FAF7F0"))) )
|
'((default (:background "#FAF7F0"))) )
|
||||||
(format "face-remapping=%S" background))
|
(format "face-remapping=%S" background))
|
||||||
(ebox-playground-flex-resize-evaluator--check
|
(ebox-playground-flex-resize-evaluator--check
|
||||||
"resize is millisecond-scale"
|
"bounded resize burst"
|
||||||
(<= elapsed
|
(<= elapsed
|
||||||
ebox-playground-flex-resize-evaluator-max-seconds)
|
ebox-playground-flex-resize-evaluator-max-seconds)
|
||||||
(format "elapsed=%.6fs threshold=%.6fs"
|
(format "elapsed=%.6fs threshold=%.6fs"
|
||||||
elapsed
|
elapsed
|
||||||
ebox-playground-flex-resize-evaluator-max-seconds))))
|
ebox-playground-flex-resize-evaluator-max-seconds))))
|
||||||
(push (format
|
(push (format
|
||||||
"RESIZE old-viewport-px=%S new-viewport-px=%S total=%.6fs rerender=%.6fs first=%.6fs max-update=%.6fs max-gap=%.6fs final=%.6fs strategy=%S projection=%S axes=%S reconciled=%S native-flex=%S tp-ops=%S cache-hits=%S cache-misses=%S"
|
"RESIZE warmups=%d samples=%d old-viewport-px=%S new-viewport-px=%S total=%.6fs p95-update=%.6fs max-update=%.6fs first=%.6fs max-gap=%.6fs final=%.6fs strategy=%S projection=%S axes=%S reconciled=%S tp-ops=%S cache-hits=%S cache-misses=%S"
|
||||||
old-width viewport-width elapsed resize-elapsed
|
warmup-publications resize-count old-width viewport-width
|
||||||
(or first-publication 0.0) max-publication max-gap
|
elapsed p95-publication max-publication
|
||||||
|
(or first-publication 0.0) max-gap
|
||||||
(or final-latency -1.0)
|
(or final-latency -1.0)
|
||||||
(plist-get report :strategy) projection-kind
|
(plist-get report :strategy) projection-kind
|
||||||
(plist-get report :viewport-axes)
|
(plist-get report :viewport-axes)
|
||||||
(plist-get report :reconciled-objects)
|
(plist-get report :reconciled-objects)
|
||||||
native-flex-calls tp-operations
|
tp-operations
|
||||||
(plist-get report :cache-hit-count)
|
(plist-get report :cache-hit-count)
|
||||||
(plist-get report :cache-miss-count))
|
(plist-get report :cache-miss-count))
|
||||||
ebox-playground-flex-resize-evaluator--output-lines)
|
ebox-playground-flex-resize-evaluator--output-lines)
|
||||||
@ -333,8 +416,8 @@ concurrent cache warming CPU work."
|
|||||||
(push "FAIL evaluator interrupted"
|
(push "FAIL evaluator interrupted"
|
||||||
ebox-playground-flex-resize-evaluator--output-lines)
|
ebox-playground-flex-resize-evaluator--output-lines)
|
||||||
nil))
|
nil))
|
||||||
(when resize-advice
|
(when (and (buffer-live-p preview) observer)
|
||||||
(advice-remove 'ebox-rerender-buffer-with-context resize-advice))
|
(ebox-buffer-set-observer preview nil))
|
||||||
(when (buffer-live-p preview)
|
(when (buffer-live-p preview)
|
||||||
(kill-buffer preview))
|
(kill-buffer preview))
|
||||||
(when (buffer-live-p source)
|
(when (buffer-live-p source)
|
||||||
|
|||||||
@ -5,12 +5,42 @@ root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
|||||||
emacs=${EMACS:-/Applications/Emacs.app/Contents/MacOS/Emacs}
|
emacs=${EMACS:-/Applications/Emacs.app/Contents/MacOS/Emacs}
|
||||||
emacsclient=${EMACSCLIENT:-/Applications/Emacs.app/Contents/MacOS/bin/emacsclient}
|
emacsclient=${EMACSCLIENT:-/Applications/Emacs.app/Contents/MacOS/bin/emacsclient}
|
||||||
server="ebox-playground-flex-evaluator-$$"
|
server="ebox-playground-flex-evaluator-$$"
|
||||||
|
fixture=$(mktemp "${TMPDIR:-/tmp}/ebox-flex-reference.XXXXXX")
|
||||||
|
|
||||||
|
require_fresh_elc() {
|
||||||
|
source_file=$1
|
||||||
|
elc_file=$2
|
||||||
|
if [ ! -r "$elc_file" ] || [ "$source_file" -nt "$elc_file" ]; then
|
||||||
|
echo "stale or missing evaluator artifact: $elc_file" >&2
|
||||||
|
echo "run make performance-prepare first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
"$emacsclient" -n -s "$server" -e '(kill-emacs 0)' >/dev/null 2>&1 || true
|
"$emacsclient" -n -s "$server" -e '(kill-emacs 0)' >/dev/null 2>&1 || true
|
||||||
|
rm -f "$fixture"
|
||||||
}
|
}
|
||||||
trap cleanup EXIT INT TERM
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
require_fresh_elc "$root/ebox-playground.el" "$root/ebox-playground.elc"
|
||||||
|
require_fresh_elc \
|
||||||
|
"$root/scripts/ebox-playground-flex-resize-evaluator.el" \
|
||||||
|
"$root/scripts/ebox-playground-flex-resize-evaluator.elc"
|
||||||
|
require_fresh_elc "$root/../ebox/ebox.el" "$root/../ebox/ebox.elc"
|
||||||
|
require_fresh_elc "$root/../ebox/ebox-surface.el" "$root/../ebox/ebox-surface.elc"
|
||||||
|
require_fresh_elc "$root/../ecss/ecss.el" "$root/../ecss/ecss.elc"
|
||||||
|
require_fresh_elc "$root/../tp/tp.el" "$root/../tp/tp.elc"
|
||||||
|
|
||||||
|
: "${EBOX_NATIVE_REFLOW_MODULE_PATH:?run make performance-prepare first}"
|
||||||
|
if [ ! -r "$EBOX_NATIVE_REFLOW_MODULE_PATH/libebox_native_reflow.dylib" ]; then
|
||||||
|
echo "prepared Ebox native module is missing" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git -C "$root" show HEAD:examples/flex-reference.ebox >"$fixture"
|
||||||
|
export EBOX_PLAYGROUND_FLEX_FIXTURE=$fixture
|
||||||
|
|
||||||
# Keep the evaluator package-only, but reproduce only the four startup values
|
# Keep the evaluator package-only, but reproduce only the four startup values
|
||||||
# that directly affect this render path. Loading the complete user init would
|
# that directly affect this render path. Loading the complete user init would
|
||||||
# add unrelated packages, timers, and UI state to the performance gate.
|
# add unrelated packages, timers, and UI state to the performance gate.
|
||||||
@ -18,12 +48,15 @@ trap cleanup EXIT INT TERM
|
|||||||
-L "$root" -L "$root/../ebox" -L "$root/../ecss" \
|
-L "$root" -L "$root/../ebox" -L "$root/../ecss" \
|
||||||
-L "$root/../tp" \
|
-L "$root/../tp" \
|
||||||
--eval '(setq load-prefer-newer t
|
--eval '(setq load-prefer-newer t
|
||||||
|
native-comp-jit-compilation nil
|
||||||
|
ebox-native-reflow-module-path
|
||||||
|
(getenv "EBOX_NATIVE_REFLOW_MODULE_PATH")
|
||||||
gc-cons-threshold most-positive-fixnum
|
gc-cons-threshold most-positive-fixnum
|
||||||
gc-cons-percentage 0.6
|
gc-cons-percentage 0.6
|
||||||
file-name-handler-alist nil
|
file-name-handler-alist nil
|
||||||
auto-window-vscroll nil)' \
|
auto-window-vscroll nil)' \
|
||||||
-l "$root/ebox-playground.el" \
|
-l "$root/ebox-playground" \
|
||||||
-l "$root/scripts/ebox-playground-flex-resize-evaluator.el"
|
-l "$root/scripts/ebox-playground-flex-resize-evaluator"
|
||||||
|
|
||||||
output=$("$emacsclient" -n -s "$server" -c -e \
|
output=$("$emacsclient" -n -s "$server" -c -e \
|
||||||
'(ebox-playground-flex-resize-evaluator-run)' 2>&1)
|
'(ebox-playground-flex-resize-evaluator-run)' 2>&1)
|
||||||
|
|||||||
@ -137,6 +137,36 @@
|
|||||||
"EXPLICIT PLACEMENT" "PUBLIC COMPOSITION"))
|
"EXPLICIT PLACEMENT" "PUBLIC COMPOSITION"))
|
||||||
(should (string-match-p (regexp-quote label) rendered)))))
|
(should (string-match-p (regexp-quote label) rendered)))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-playground-flex-evaluator-uses-public-observation ()
|
||||||
|
"Keep the Flex resize gate on public Ebox reports without advice."
|
||||||
|
(let ((source (with-temp-buffer
|
||||||
|
(insert-file-contents
|
||||||
|
(expand-file-name
|
||||||
|
"scripts/ebox-playground-flex-resize-evaluator.el"
|
||||||
|
ebox-playground-directory))
|
||||||
|
(buffer-string)))
|
||||||
|
(runner (with-temp-buffer
|
||||||
|
(insert-file-contents
|
||||||
|
(expand-file-name "scripts/flex-resize-evaluator.sh"
|
||||||
|
ebox-playground-directory))
|
||||||
|
(buffer-string)))
|
||||||
|
(makefile (with-temp-buffer
|
||||||
|
(insert-file-contents
|
||||||
|
(expand-file-name "Makefile" ebox-playground-directory))
|
||||||
|
(buffer-string))))
|
||||||
|
(should (string-match-p "ebox-buffer-set-observer" source))
|
||||||
|
(should (string-match-p "evaluator-warmup-count 5" source))
|
||||||
|
(should (string-match-p "evaluator-sample-count 30" source))
|
||||||
|
(should (string-match-p "per-update p95 budget" source))
|
||||||
|
(should (string-match-p "EBOX_PLAYGROUND_FLEX_FIXTURE" runner))
|
||||||
|
(should (string-match-p "show HEAD:examples/flex-reference.ebox" runner))
|
||||||
|
(should (string-match-p "performance-prepare:" makefile))
|
||||||
|
(should (string-match-p "native-build" makefile))
|
||||||
|
(should-not (string-match-p "-l \"\$root/ebox-playground.el\"" runner))
|
||||||
|
(dolist (private '("ebox--" "advice-add" "advice-remove"
|
||||||
|
"ebox-native-reflow--"))
|
||||||
|
(should-not (string-match-p (regexp-quote private) source)))))
|
||||||
|
|
||||||
(ert-deftest ebox-playground-keeps-layout-in-ebox-source ()
|
(ert-deftest ebox-playground-keeps-layout-in-ebox-source ()
|
||||||
"Keep concrete gallery content out of the generic Elisp runner."
|
"Keep concrete gallery content out of the generic Elisp runner."
|
||||||
(let ((runner (with-temp-buffer
|
(let ((runner (with-temp-buffer
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user