Open seagle0128 opened 3 years ago
posframe只有在极少数的情况下才会重建frame,大多数都是复用已经有的frame
今天看到这个帖子,确实存在性能问题,尤其内存占用厉害。
https://emacs-china.org/t/emacs-savehist-printable-ivy-posframe-read/16797
我感觉可能是不小心触发了某种潜在的 bug, 就 posframe 而言,也就是移动缩放 frame ,不太可能占用7G内存
理论上如此,但值得好好分析。我也发现用了posframe之后,尤其是ivy-posframe,比之前占用内存多太多。以前是300M左右,现在长期700M+。
有没有使用 emacs -Q 测试过 ivy-posframe ?
刚简单做了一个测试,供参考:
GNU Emacs 28.0.50, macOS Big Sur, emacs -Q
,打开ivy-mode
, 打开相同的几个文件,做一些操作,大概占用~70M
ivy-posframe
: ~100M mini-frame
: ~80M经过一些操作,一段时间后:
ivy-posframe
: ~160M mini-frame
: ~120M如果差异只有40M的话,还是可以忍受的。。。;)
关键是时间长了,差距可能越来越大 😂
http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=246e107d73e633c06478eaf021776acedef9dafc
不知道这个对 posframe 的速度有没有提升?
(benchmark 1000
'(redraw-frame))
这个在果子机上速度如何?
(benchmark 1000 '(redraw-frame))
这个在果子机上速度如何?
测试三次,结果如下:
emacs -Q
:
Elapsed time: 0.475326s
Elapsed time: 0.468543s
Elapsed time: 0.460630s
In Centaur Emacs:
Elapsed time: 5.598229s
Elapsed time: 6.027011s
Elapsed time: 6.101822s
差别很明显啊,不知道是哪里的原因
Update: 作了下profile,仍然看不出瓶颈。猜测是UI配置之类的导致?
在linux下, 1000次用时 0.0005
(defun posframe--set-frame-position (posframe position
parent-frame-width
parent-frame-height)
"Move POSFRAME to POSITION.
This need PARENT-FRAME-WIDTH and PARENT-FRAME-HEIGHT"
(unless (and (equal position posframe--last-posframe-pixel-position)
;; When working frame's size change, re-posit
;; the posframe.
(equal posframe--last-parent-frame-size
(cons parent-frame-width parent-frame-height))
(equal posframe--last-posframe-displayed-size
(cons (frame-pixel-width posframe)
(frame-pixel-height posframe))))
(set-frame-position posframe (car position) (cdr position))
(setq-local posframe--last-posframe-pixel-position position)
(setq-local posframe--last-parent-frame-size
(cons parent-frame-width parent-frame-height))
(setq-local posframe--last-posframe-displayed-size
(cons (frame-pixel-width posframe)
(frame-pixel-height posframe))))
;; Make posframe's posframe--frame visible
(unless (frame-visible-p posframe)
(make-frame-visible posframe)
;; Fix issue: https://github.com/tumashu/ivy-posframe/pull/30
;; (redraw-frame posframe)
))
看看这个版本对速度有没有影响
mac下emacs的UI效率确实不行,不过linux的UI不稳定,经常会有闪烁。 刚才那个问题找到原因了,居然是persp-mode引起的 😂
是不是 persp-mode 将 child-frame 保存了,导致速度拖慢了。
是不是 persp-mode 将 child-frame 保存了,导致速度拖慢了。
还不清楚,刚查了下,好像并没有保存child frame,相应的buffer我都ignore了。但可能保存这类frame的配置。再研究下。
研究了下 https://github.com/tumashu/ivy-posframe/pull/30 ,感觉用redraw不合理啊。frame-delete肯定不行,理想情况是清空buffer才是效率最高的。
当时细节不知道了,我感觉是遇到刷新缓慢的问题,所以强制 redraw,好像也是果子机遇到的
测试了一小会儿,速度有所提升,感受不是非常明显。但是会有闪烁,另外内存还是会增长,不过增长幅度目前还没法判断。
在linux下, 1000次用时 0.0005
晚上又研究了一会,发现跟persp-mode没有必然联系,只跟frame大小有关。因为我用的是4K显示屏,全屏时就是6s左右,默认窗口大小(80x30)就是0.4s左右。Linux下跟窗口大小好像影响没这么明显。
我没有用 persp-mode,不过测试结果也是5秒左右。另外我发现 posframe-run-hidehandler
被调用得很频繁(因为被加到了post-command-hook里),这对速度有影响吗?还有速度影响最明显的是用counsel搜索的时候,counsel--async-filter
被非常频繁地调用 (好像每次调用都会update buffer内容),不知道有没有联系。
hidehandler 看起来好像没有运行速度慢的地方,所以我感觉可能不是瓶颈。
去除 (redraw-frame posframe) 后,https://github.com/tumashu/ivy-posframe/pull/30 这个问题不知道存不存在? @seagle0128
我写了一个简单的 benchmark 工具,暂时还比较粗糙,大家可以运行一下,看看效果如何
https://github.com/tumashu/posframe/blob/master/posframe-benchmark.el
去除 (redraw-frame posframe) 后,tumashu/ivy-posframe#30 这个问题不知道存不存在?
@tumashu 去掉这个问题会存在,内容没有被清理,窗口会有一定的闪烁。
我没有用 persp-mode,不过测试结果也是5秒左右。另外我发现
posframe-run-hidehandler
被调用得很频繁(因为被加到了post-command-hook里),这对速度有影响吗?还有速度影响最明显的是用counsel搜索的时候,counsel--async-filter
被非常频繁地调用 (好像每次调用都会update buffer内容),不知道有没有联系。
@zhenwenc 对,跟persp-mode没有关系,跟窗口大小有关。我去掉persp-mode性能提高就是因为窗口是默认大小并没有最大化。posframe-run-hidehandler 我认为有不是瓶颈, 你可以profile再看看到底CPU占用如何。
我写了一个简单的 benchmark 工具,暂时还比较粗糙,大家可以运行一下,看看效果如何
https://github.com/tumashu/posframe/blob/master/posframe-benchmark.el
默认最新版:
* Posframe Benchmark
** Benchmark ‘font-at’ 10000 times ...
Elapsed time: 0.237086s
** Benchmark ‘redraw-display’ 10000 times ...
Elapsed time: 59.314862s
** Benchmark ‘remove-text-properties’ 10000 times ...
Elapsed time: 0.003365s
** Benchmark ‘mouse-position’ 10000 times ...
Elapsed time: 1.041860s
** Benchmark ‘default-font-width’ 10000 times ...
Elapsed time: 0.216869s
** Benchmark ‘posframe--get-font-height’ 10000 times ...
Elapsed time: 0.005082s
** Benchmark ‘posframe--mouse-banish’ 10000 times ...
Elapsed time: 0.001690s
** Benchmark ‘frame-parameter’ 10000 times ...
Elapsed time: 0.045978s
** Benchmark ‘set-mouse-position’ 10000 times ...
Elapsed time: 0.240378s
** Benchmark ‘posn-at-point’ 10000 times ...
Elapsed time: 219.611200s (1.041883s in 6 GCs)
** Benchmark ‘set-frame-parameter’ 10000 times ...
Elapsed time: 0.006588s
** Benchmark ‘raise-frame’ 10000 times ...
Elapsed time: 1.084977s
* Finished.
去掉了redraw-frame 之后:
* Posframe Benchmark
** Benchmark ‘font-at’ 10000 times ...
Elapsed time: 0.203783s
** Benchmark ‘redraw-display’ 10000 times ...
Elapsed time: 60.493191s
** Benchmark ‘remove-text-properties’ 10000 times ...
Elapsed time: 0.002599s
** Benchmark ‘mouse-position’ 10000 times ...
Elapsed time: 1.046413s
** Benchmark ‘default-font-width’ 10000 times ...
Elapsed time: 0.223130s
** Benchmark ‘posframe--get-font-height’ 10000 times ...
Elapsed time: 0.005315s
** Benchmark ‘posframe--mouse-banish’ 10000 times ...
Elapsed time: 0.001859s
** Benchmark ‘frame-parameter’ 10000 times ...
Elapsed time: 0.176227s (0.134239s in 1 GCs)
** Benchmark ‘set-mouse-position’ 10000 times ...
Elapsed time: 0.224940s
** Benchmark ‘posn-at-point’ 10000 times ...
Elapsed time: 180.730515s (0.782196s in 5 GCs)
** Benchmark ‘set-frame-parameter’ 10000 times ...
Elapsed time: 0.004266s
** Benchmark ‘raise-frame’ 10000 times ...
Elapsed time: 0.670495s
* Finished.
我这边类似这样, debian linux, 1000次的测试
* Posframe Benchmark
** Benchmark ‘font-at’ 1000 times ...
Elapsed time: 0.000333s
** Benchmark ‘redraw-display’ 1000 times ...
Elapsed time: 0.000595s
** Benchmark ‘redraw-frame’ 1000 times ...
Elapsed time: 0.000904s
** Benchmark ‘remove-text-properties’ 1000 times ...
Elapsed time: 0.000337s
** Benchmark ‘mouse-position’ 1000 times ...
Elapsed time: 0.086048s
** Benchmark ‘default-font-width’ 1000 times ...
Elapsed time: 0.006293s
** Benchmark ‘posframe--get-font-height’ 1000 times ...
Elapsed time: 0.000271s
** Benchmark ‘posframe--mouse-banish’ 1000 times ...
Elapsed time: -0.004739s
** Benchmark ‘frame-parameter’ 1000 times ...
Elapsed time: 0.009540s
** Benchmark ‘set-mouse-position’ 1000 times ...
Elapsed time: 0.000167s
** Benchmark ‘posn-at-point’ 1000 times ...
Elapsed time: 0.441456s
** Benchmark ‘set-frame-parameter’ 1000 times ...
Elapsed time: 0.000399s
** Benchmark ‘raise-frame’ 1000 times ...
Elapsed time: 3.044742s
* Finished.
(defun ivy-posframe--display (str &optional poshandler)
"Show STR in ivy's posframe with POSHANDLER."
(if (not (posframe-workable-p))
(ivy-display-function-fallback str)
(with-ivy-window
(apply #'posframe-show
ivy-posframe-buffer
:font ivy-posframe-font
:string str
;; :position (point)
:poshandler poshandler
:background-color (face-attribute 'ivy-posframe :background nil t)
:foreground-color (face-attribute 'ivy-posframe :foreground nil t)
:internal-border-width ivy-posframe-border-width
:internal-border-color (face-attribute 'ivy-posframe-border :background nil t)
:override-parameters ivy-posframe-parameters
:refposhandler ivy-posframe-refposhandler
(funcall ivy-posframe-size-function))
(ivy-posframe--add-prompt 'ignore)))
(with-current-buffer ivy-posframe-buffer
(setq-local truncate-lines ivy-truncate-lines)))
试试这个
redraw-display 性能相差太大了。
@tumashu 你是指去掉 (redraw-frame posframe)
,用新的 ivy-posframe--display
对吗?结果是会残留之前的内容,闪一下显示新内容。
不是,我是看见你的机器上 posn-at-point 速度也极其慢,所以我想测试一下是不是这个函数的调用导致的卡顿。
** Benchmark ‘posn-at-point’ 10000 times ...
Elapsed time: 219.611200s (1.041883s in 6 GCs)
最好的方法是 不使用 redraw-display 或者 redraw-frame, 但不知道怎么搞
ivy-posframe--display 这个没用, 下载最新的 posframe 代码测试吧,看速度怎么样。
现在用的就是最新代码,感觉不明显。
顺便提一句,隐藏minibuffer prompt那个实在tricky啊,mini-frame是怎么干的呢,好像所有都放到child frame了
隐藏minibuffer prompt那个实在tricky啊,
学 helm 的 :-)
@seagle0128 用最新的代码,并且把 redraw-frame 删除,看看速度有没有提升,如果没有提升,那估计还有其它瓶颈
@tumashu 性能有一定提升,但是闪烁也挺难受啊 😂
@seagle0128 要不编译一下emacs master试试? 因为: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=246e107d73e633c06478eaf021776acedef9dafc
@tumashu 我用的就是最新版,6/2编译的。去掉 redraw-frame 性能会好些,有点闪烁,其实也还好,就怕强迫症 😂
我倒是感觉, redraw 和 pos-at-point 这两个函数在果子机上极其缓慢,可能它们底层C代码存在性能问题,因为我看见这两天 emacs devel 上也在讨论 frame 性能相关的内容,建议在 emacs-devel 上问问大牛
嗯,我这两天再抽空编译下新版本,看看有没有改善。
刚才编译了新版本,同样的分辨率下测试 (benchmark-run 1000 (redraw-frame))
,时间在 ~2s左右,提升不少啊!
posframe 体验有提升没?
有一定提升,还在观察中。。。
更新下,最新版gccemacs使用ivy-posframe,性能提升明显,内存也有所改善。推荐大家试试。
666,最近我看到一个大牛整改 refactor macox 的 window 相关的代码,不知道会不会对性能有所提升
看来换新开发者了啊,不容易 👍🏻👍🏻 😄😄
应该叫有新的大牛加入。。。。 :-)
刚编译了新版本,gccemacs越来越流畅了,继续观察中。。。 😄
@seagle0128 能不能运行一下 posframe-benchmark, 看看哪些函数速度提升了。
我也编译了gccemacs,使用两天感觉确实流畅不少。发现 flycheck-posframe dismiss 延迟了,大概是为了优化性能?
* Posframe Benchmark
** Benchmark ‘font-at’ 1000 times ...
Elapsed time: 0.013770s
** Benchmark ‘redraw-display’ 1000 times ...
Elapsed time: 1.318676s
** Benchmark ‘redraw-frame’ 1000 times ...
Elapsed time: 1.210649s
** Benchmark ‘remove-text-properties’ 1000 times ...
Elapsed time: 0.000453s
** Benchmark ‘mouse-position’ 1000 times ...
Elapsed time: 0.080340s
** Benchmark ‘default-font-width’ 1000 times ...
Elapsed time: 0.018745s
** Benchmark ‘posframe--get-font-height’ 1000 times ...
Elapsed time: 0.000092s
** Benchmark ‘posframe--mouse-banish’ 1000 times ...
Elapsed time: 0.000119s
** Benchmark ‘frame-parameter’ 1000 times ...
Elapsed time: 0.004652s
** Benchmark ‘set-mouse-position’ 1000 times ...
Elapsed time: 0.019597s
** Benchmark ‘posn-at-point’ 1000 times ...
Elapsed time: 0.906148s (0.162083s in 1 GCs)
** Benchmark ‘posn-x-y’ 1000 times ...
Elapsed time: 1.023758s (0.267148s in 2 GCs)
** Benchmark ‘posn-object-x-y’ 1000 times ...
Elapsed time: 0.883263s (0.134518s in 1 GCs)
** Benchmark ‘set-frame-parameter’ 1000 times ...
Elapsed time: 0.000449s
** Benchmark ‘raise-frame’ 1000 times ...
Elapsed time: 0.032924s
* Finished.
@seagle0128 能不能运行一下 posframe-benchmark, 看看哪些函数速度提升了。
* Posframe Benchmark
** Benchmark ‘font-at’ 1000 times ...
Elapsed time: 0.017461s
** Benchmark ‘redraw-display’ 1000 times ...
Elapsed time: 1.266655s
** Benchmark ‘redraw-frame’ 1000 times ...
Elapsed time: 1.259094s
** Benchmark ‘remove-text-properties’ 1000 times ...
Elapsed time: 0.000298s
** Benchmark ‘mouse-position’ 1000 times ...
Elapsed time: 0.117805s
** Benchmark ‘default-font-width’ 1000 times ...
Elapsed time: 0.021617s
** Benchmark ‘posframe--get-font-height’ 1000 times ...
Elapsed time: 0.000495s
** Benchmark ‘posframe--mouse-banish’ 1000 times ...
Elapsed time: 0.000155s
** Benchmark ‘frame-parameter’ 1000 times ...
Elapsed time: 0.003491s
** Benchmark ‘set-mouse-position’ 1000 times ...
Elapsed time: 0.020867s
** Benchmark ‘posn-at-point’ 1000 times ...
Elapsed time: 1.083250s
** Benchmark ‘posn-x-y’ 1000 times ...
Elapsed time: 1.211351s (0.165975s in 1 GCs)
** Benchmark ‘posn-object-x-y’ 1000 times ...
Elapsed time: 1.062713s
** Benchmark ‘set-frame-parameter’ 1000 times ...
Elapsed time: 0.000392s
** Benchmark ‘raise-frame’ 1000 times ...
Elapsed time: 0.042280s
* Finished.
https://github.com/tumashu/posframe/blob/739d8fd1081bdd0d20dee9e437d64df58747b871/posframe.el#L301-L307
请教下,我看到这里判断arg是否被修改,如果修改过就会删除并重新创建子窗口。很多场景下会造成一定程度的闪烁,打开时(比如 ivy-posframe)会有一点延迟。有没有可能直接用
modify-frame-parameters
来复用child frame呢?这样是否能提高性能?最近我在看mini-frame,发现在很多场景下性能会比posframe高些。mini-frame就是尽量复用已经创建的frame。不过,由于在Linux上表现不佳,我还是倾向于使用posframe,但是希望能改进性能。希望您能看看?很多细节我还不是很明白。谢谢!