Emacs를 느리게 만드는 매우 긴 줄을 어떻게 방지합니까?


72

방문하는 파일에 줄 바꿈 수에 따라 성능이 크게 다릅니다.

다음은 예입니다. 두 개의 JSON 파일이 있습니다.

$ wget https://github.com/Wilfred/ReVo-utilities/blob/a4bdc40dd2656c496defc461fc19c403c8306d9f/revo-export/dictionary.json?raw=true -O one_line.json
$ python -m json.tool <one_line.json >pretty_printed.json

내용이 같은 두 개의 JSON 파일입니다. one_line.json개행없이 18MiB의 JSON입니다. pretty_printed.json줄 바꿈과 공백이 추가되어 41MiB가됩니다.

그러나 여러 줄로 나뉘어 진 더 큰 파일은 Javascript 모드와 Fundamental 모드 모두에서 Emacs에서 열 때 훨씬 빠릅니다.

실제로 Emacs가 바이트 수가 적기 때문에 긴 줄에서 성능이 좋지 않은 이유는 무엇입니까? Emacs 외부의 데이터를 다시 포맷하지 않고 성능을 향상시키기 위해 할 수있는 일이 있습니까?


2
실제로 대답은 아니지만 사용 중일 수 있습니다. View Large Files(vlf) 는 큰 파일을 일괄 적 으로로드하여 편집하는 데 도움이되는 작은 모드입니다 . 면책 조항 : 나는 그것을 사용한 적이 없으며 긴 줄을 일괄 처리하는지 여부를 모르겠습니다 .
elemakil

3
이런 종류의 행동을 알고, 특히 긴 줄을 뱉어내는 로그를 읽지 않도록 스스로를 보호하려고 할 때, 나는 종종 $ tail -f /some/file | fold -s쉘 버퍼에서 와 같은 일 을합니다. 이것은 편집에는 좋지 않지만 읽기에는 많은 도움이됩니다.
wvxvw

답변:


50

Emacs의 긴 줄 처리는 잘 최적화되지 않았습니다. 여러 작업을 위해 Emacs는 전체 라인을 반복적으로 스캔해야합니다. 예를 들어, 라인을 표시하려면 Emacs는 라인의 높이를 파악해야하며, 가장 높은 글리프를 찾으려면 전체 라인을 스캔해야합니다. 또한 양방향 디스플레이를 검색하는 데 많은 시간이 소요됩니다. 예를 들어, cache-long-line-scans( cache-long-scans24.4에서 이름이 바뀐) docstring에서 추가 정보를 얻을 수 있습니다 .

당신이 시도하고 설정하면 볼 수 있습니다 bidi-paragraph-direction하려면 left-to-right[설정 당신을 위해 속도를 향상 bidi-display-reorderingnil더 많거나 적은 같은 않지만 내부 / 디버깅 목적만을위한 것입니다]. 이것은 라인 스캔에 중요한 기여자를 제거하지만 슬프게도 유일한 것은 아닙니다.

가장 좋은 방법은 줄 바꿈을 추가하는 것입니다. 예 python -c 'import json, sys ; json.dump(json.load(sys.stdin), sys.stdout, indent=2)'를 들어 JSON 파일을 파이프하여 개행을 추가하고 일반적으로 가독성을 향상시킬 수 있습니다.


4
호기심으로, 이것은 알고리즘 적으로 개선 될 수없는 것입니까?
PythonNut

9
편집기의 기본 데이터 구조를 선택할 때 특정 장단점 중에서 선택해야합니다. Emacs는 삽입 및 삭제를위한 공간 효율적인 데이터 구조 인 갭 버퍼를 사용 하지만 줄 바꿈을 위해 순차적으로 스캔해야하기 때문에 라인 기반 작업이 느려집니다. 이맥스는 다른 데이터 구조를 사용할 수 있지만 다른 작업은 느려질 수 있습니다. 이맥스는 이미 라인 캐시를 사용하지만 모든 상황에서 실제로 도움이되는 것은 아닙니다. 따라서 알고리즘 적으로 쉽게 개선되지는 않지만 프로파일 링 및 최적화는 결코 아프지 않습니다. :-)
Jorgen Schäfer

4
(setq-default bidi-display-reordering nil)-일부 사용자는 이것이 로컬 변수 인 버퍼 로컬 변수라는 것을 인식하지 못할 수 있습니다.이 변수 는 사용자가 전역 변수를 원하는 정도로 기본 설정 이 필요할 수 있습니다. 나는 그것을 init.el몇 년 전에 추가했으면 좋겠지 만 적어도 지금은 거기에 있습니다. 너무 감사합니다!!!
Lawlist

내 경우는 큰 improvent (base64로 문서 본문 정말 긴 JSON 라인)은 아니었지만 beign 동결에 많은 도움이
anquegi

1
BIDI 코드를 작성한 현재 Emacs 관리자 인 Eli는 다음과 같이 스위치를 끄는 것에 대해 다음과 같이 기록합니다 bidi-display-reordering. 그리고 심지어 버그도있다 (코드의 일부가이 변수가 절대 0이 아니라는 가정하에 작성 되었기 때문이다 ").
Clément

18

축소 된 jquery 사본을 사용하여 이에 대한 간단한 실험을 수행했습니다. font-lock-mode그리고 flycheck-mode모두가 그랬던 것처럼, 속도 저하에 기여 js2-mode하고 prettify-symbols-mode. line-number-mode그리고 column-number-mode작은 영향을 미쳤다. 성능이 비교적 빠르지 만 모든 다른 모드를 끈 후에는. 사용 C-h m가능한 다른 모드를 사용하거나 사용하지 않도록 시작하거나로 전환하십시오 fundamental-mode.

흥미롭게도 hexl-mode열이 상당히 짧았지만 문제없이 파일을 통과 할 수있었습니다. 불행히도 visual-line-mode실제로 상황이 느려졌습니다.

내 생각에 구문 테이블은 줄 끝에서 처리를 중단하고 기꺼이 한 줄에 있으면 모든 업데이트에서 모든 것을 다시 분석해야합니다.


2
Flycheck의 트래커에서 버그 보고서를 열 수 있습니까? 나는 우리가 문제를 일으키는 긴 줄을 원하지 않는다고 확신하며, Emacs + Flycheck는 Emacs보다 나쁘지 않아야합니다 (여전히 나쁩니다).
Clément

16

http://www.emacswiki.org/emacs/OverLongLineMode를 업로드했습니다 .

이 라이브러리를 사용하면 fundamental-mode일반 모드 대신 파일에 변형을 사용할 수 있는 단순한 선 길이 임계 값을 설정할 수 있습니다 (프로그래밍 모드에만 해당).

기본적으로이 줄을 따라 무언가가 Emacs에 추가 될 수 있지만, 이러한 파일을 발견했을 때 크롤링이 느려지는 Emacs의 주요 문제에 대한 임시 해결 방법이 될 수 있습니다.

nb 이것은이 답변에 처음 게시 한 코드를 개선 한 것이지만 여전히 진행중인 작업입니다. 테스트는 최소화되었습니다. 의견을 환영합니다.

기본적으로 지원할 다른 파생되지 css-mode않은 prog-mode주요 모드에 대한 제안 도 환영합니다.


1
이제 더 향상되었으며 수치스럽게 so-long.el :)으로 이름이 변경되었습니다 (위 링크가 리디렉션 됨). 이것으로 더 많은 일을 할 수 있지만 100 % 기능적이고 유용합니다.
Phil

이것은 정말 좋은 해결책입니다 (MELPA에서보고 싶을 것입니다).하지만 one_line.json을 열 때 내 Emacs 인스턴스는 여전히 매우 느립니다. 원래 주 모드를 처음 활성화하지 않으면 훨씬 빠를 것이라고 생각합니다.
Wilfred Hughes

3
이것을 다시 읽고 질문에서 one_line.json 파일을 사용하여 default-config Emacs 25.3 및 26.0.91을 기다리는 동안 포기했습니다 (1 분 이상 기다린 후). config를 so-long.elactive로 설정하면 2 초 안에 파일이 열립니다. 실제로 파일을 편집하는 것은 여전히 ​​문제가 있습니다 (예 : '다음 줄'로 이동하는 데 시간이 오래 걸릴 것입니다). 그러나 그럼에도 불구하고 이것이 내가 작성한 라이브러리의 유용성에 대한 내 믿음을 회복 시키므로 계획을 다시 시작해야합니다. GNU ELPA에 추가
phils

1
아직 (M) ELPA에 있습니까?
binki

3
상태 보고서 : so-long.elEmacs 27의 현재 개발 버전에 버전 1.0 (수많은 개선 사항 포함)이 포함되어 있으며 가까운 시일 내에 GNU ELPA를 통해 (이전 버전의 Emacs) 사용할 수 있습니다.

7

그 차이가로 인한 것임을 알 수 있습니다 font-lock. 윈도우에서 볼 수있는 파일의 서브 세트에서 폰트 화가 수행 될 때, 그것은 전체 시맨틱 단위를 포함하도록 먼저 폰트 화 영역을 확장함으로써 진행된다. 이에 대한 font-lock-extend-region-functions코드를 참조하십시오 . 전체 라인을 포함하도록 영역을 확장하는 것이 일반적입니다. 줄이 너무 길면 실제로 표시되는 것보다 훨씬 더 많은 내용의 청크에서 글꼴 화가 수행 될 수 있습니다.

또한 줄 바꿈 자체에 의미 정보가있는 경우 해당 문자가없는 경우 글꼴 잠금에 대한 정규 표현식 패턴이 일치하는지 여부를 판별하기 위해 추가 스캔을 수행해야 할 수도 있습니다.


7

일반적으로 긴 줄을 풀고 태그 (예 : HTML, XML, JSON)로 들여 쓰기합니다.

이러한 작업을 가능하게하기 위해 다음을 추가합니다.

(setq line-number-display-limit large-file-warning-threshold)
(setq line-number-display-limit-width 200)

(defun my--is-file-large ()
  "If buffer too large and my cause performance issue."
  (< large-file-warning-threshold (buffer-size)))

(define-derived-mode my-large-file-mode fundamental-mode "LargeFile"
  "Fixes performance issues in Emacs for large files."
  ;; (setq buffer-read-only t)
  (setq bidi-display-reordering nil)
  (jit-lock-mode nil)
  (buffer-disable-undo)
  (set (make-variable-buffer-local 'global-hl-line-mode) nil)
  (set (make-variable-buffer-local 'line-number-mode) nil)
  (set (make-variable-buffer-local 'column-number-mode) nil) )

(add-to-list 'magic-mode-alist (cons #'my--is-file-large #'my-large-file-mode))

XML의 경우 정규식으로 줄을 나눕니다 C-M-% >< RET >NL< RET !.

Emacs가 긴 줄을 나눈 후 많은 *-modes코드를 다시 들여 쓰기 할 수 있습니다.

참고 : 열등한 프로세스가 긴 줄을 생성 할 때 속도 저하를 방지하는 방법은 무엇입니까?


4

이 문제에 대한 내 자신의 솔루션을 여기에 만들었습니다 : https://github.com/rakete/too-long-lines-mode

필자는 매우 긴 행의 버퍼를 기본 모드로 전환하는 필 솔루션에 만족하지 않았으며 구문 강조 표시 및 기타 주요 모드 기능을 유지할 수있는 솔루션을 원했습니다. 그래서 오버레이를 사용하여 지나치게 긴 줄의 대부분의 문자를 숨기는 부 모드를 만들었습니다.

이는 문제를 해결하고 기본 모드로 돌아 가지 않고도 매우 긴 행의 버퍼에서도 emacs를 사용할 수있게합니다.


2

내 Emacs 설정에는 맞춤 글꼴이있는 모드가 font-lock-defaults있습니다. 단일 페이지 다운은 30 초를 사용하여 30000 자 라인의 일부를 표시합니다. 이 속도 저하는 정규식 역 추적을 줄임으로써 수정되었습니다. 대신에:

  ( ". *는 불완전한 명령으로 끝났습니다 *"0 font-lock-comment-face

이 작업을 수행

  ( "^. \ {1,80 \}은 (는) 불완전한 명령으로 끝났습니다 *"0 font-lock-comment-face

이것은 질문에 대한 답변이 아니며 구체적으로 font-lock-defaults또는 정규 표현식과 일치 하지 않습니다 .
Drew

1
이상적인 정규식 이하가 @ 드류 있다 하지만 ... 긴 줄에 느린 글꼴 - 잠금 만들기
wasamasa

1
@wasamasa : 그렇습니다. 질문 자체가 너무 광범위합니다 (IMO). 긴 줄을 포함 할 때 이맥스 속도를 늦출 수있는 많은 것들이 있습니다 (그리고 어떤 행동에 대해?).
Drew

3
질문이 광범위하다고 생각하지 않습니다 ( " 긴 줄로 인해 Emacs가 느려지 는 이유 ")? 나는 그 대답이 그 질문을 다루지 않는다고 생각하지도 않는다 ( " 한가지 가능한 이유 는 차선의 정규 표현식이다"). 다른 답변은 다른 이유를 해결할 수 있습니다. 긴 줄이있는 파일을 여는 것은 여러 가지 이유로 문제가 될 수 있기 때문에 주제를 광범위하게 다루지는 않습니다. 때로는 이러한 파일이 있으므로 Emacs를 사용하여 파일을보아야합니다.
tarsius

1

내 셸 모드 버퍼 (Mx 셸)에서 sed -r 's/(.{2000}).*/\1/' -u긴 줄을 피하기 위해 파이핑을 합니다.


질문의 두 번째 부분 인 성능 향상 방법에 대한 답변입니다. " 이맥스가 왜 긴 줄로 성능이 좋지 않습니까?"
Drew

0

dired-mode긴 줄이 있는 큰 파일 을 열려면 다음 기능을 사용하십시오 .

(defun dired-find-file-conservatively ()
   (interactive)
   (let ((auto-mode-alist nil))
     (dired-find-file)
     ;; disable costly modes
     (fundamental-mode)
     (setq-local bidi-display-reordering nil)
     (when (boundp 'smartparens-mode)
       (smartparens-mode -1))))

(define-key dired-mode-map (kbd "S-<return>") 'dired-find-file-conservatively)

0

다음은 emacs-devel 에서 가져온 해결 방법입니다 .

(add-hook 'find-file-hook
          (defun my-find-file-care-about-long-lines ()
            (save-excursion
              (goto-char (point-min))
              (when (and (not (eq major-mode 'image-mode))
                         (search-forward-regexp ".\\{2000\\}" 50000 t)
                         (y-or-n-p "Very long lines detected - enable 
longlines-mode? "))
                (require 'longlines)
                (longlines-mode +1)))))

24.4 현재 Emacs에서는에 longlines-mode의해 사용되지 않는 것으로 표시되었습니다 visual-line-mode.
Alexander I.Grafov

그러나 두 기능은 뒤에서 매우 다른 작업을 수행 visual-line-mode하며 문제를 해결하는 데 도움이되지 않지만 문제는 해결 longlines-mode하지 못합니다. 이러한 이유로 longlines.el이 더 이상 사용되지 않는 상태로 복원 될 것으로 예상합니다.
필리스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.