Çok uzun çizgilerin Emac'leri yavaşlatmasını nasıl önlerim?


72

Ziyaret ettiğim dosyada kaç tane yeni satır olduğuna bağlı olarak oldukça farklı performanslar görüyorum.

İşte bir örnek. İki JSON dosyam var:

$ 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

Bunlar aynı içeriğe sahip iki JSON dosyasıdır. one_line.json189 MB of JSON. pretty_printed.jsonyeni satırları ve boşlukları ekledi, 41MiB yapıyor.

Bununla birlikte, birçok satıra bölünmüş daha büyük dosya, hem Javascript modunda hem de Temel modda, Emacs'ta açmak için çok daha hızlıdır.

Emac'lar neden aslında daha az bayt olduğundan uzun çizgilerle bu kadar düşük performans gösteriyor? Emacs dışındaki verileri yeniden biçimlendirmeden performansı iyileştirmek için yapabileceğim bir şey var mı?


2
Gerçekten bir cevap değil, ancak kullanımı olabilir: View Large Files(vlf) , büyük dosyaları gruplar halinde yükleyerek düzenlemeye yardımcı olan küçük bir moddur . Feragatname: Hiç kullanmadım ve gruplar halinde uzun çizgiler kullanıp kullanmadığını da bilmiyorum .
elemakil

3
Bu tür davranışları bilmek ve özellikle uzun bir çizgiye yayılan bir kütüğü okumaktan kendimi korumaya çalışırken, genellikle $ tail -f /some/file | fold -skabuk tamponunda olduğu gibi bir şey yapıyorum . Bu, düzenleme için iyi bir şey değil, ama okumaya çok yardımcı oluyor.
wvxvw

Yanıtlar:


50

Emacs'in uzun hatları kullanması pek iyi bir şekilde optimize edilmemiştir. Bir dizi işlem için, Emacs tüm çizgiyi tekrar tekrar taramak zorundadır. Örneğin, bir çizgi görüntülemek için Emacs, en uzun glifi bulmak için tüm çizgiyi taramayı gerektiren çizginin yüksekliğini bulmak zorundadır. Ek olarak, iki yönlü ekran taraması çok fazla zaman alır. Örneğin, ek belgelerine ek bilgi alabilirsiniz cache-long-line-scans( cache-long-scans24.4'te yeniden adlandırılmıştır ).

Sen denemek ve ayar olmadığını görebilirsiniz bidi-paragraph-directioniçin left-to-right[ayarı sizin için hızını artırır bidi-display-reorderingiçin nil, aşağı yukarı aynı yapar ama iç / hata ayıklama amacıyla sadece içindir]. Bu, çizgi taramalarına önemli bir katkıda bulunanı kaldırıyor, ancak ne yazık ki yalnızca biri değil.

En iyi seçenek yeni satırlar eklemektir. Bir JSON dosyasını örneğin python -c 'import json, sys ; json.dump(json.load(sys.stdin), sys.stdout, indent=2)'yeni hatlar eklemek ve genel olarak okunabilirliği artırmak için aracılığıyla yönlendirebilirsiniz .


4
Merak, algoritmik olarak geliştirilemeyecek bir şey mi?
PythonNut

9
Bir editörün altında yatan veri yapısını seçerken, bazı artılar ve eksiler arasında seçim yapmalısınız. Emacs, yerleştirme ve silme için yüksek oranda alan verimli bir veri yapısı olan bir boşluk arabelleği kullanır , ancak yeni bir satır için sırayla taramanız gerektiğinden, satır tabanlı işlemleri yavaşlatır. Emac'lar farklı bir veri yapısı kullanabilirdi, ancak bu diğer işlemleri yavaşlatır. Emacs zaten bir satır önbelleği kullanıyor, ancak bu her durumda gerçekten yardımcı olmuyor. Dolayısıyla, algoritmik olarak kolayca geliştirilemez, ancak profil oluşturma ve optimizasyon asla zarar vermez. :-)
Jorgen Schäfer

4
(setq-default bidi-display-reordering nil)- bazı kullanıcılar bunun bir tampon yerel değişken olduğunu fark etmeyebilir; bu, kullanıcının bunun global olmasını istediği ölçüde varsayılan bir ayar gerektirebilir. Keşke bunu init.elyıllar önce ekleyebilseydim ... ama en azından şimdi orada. Çok teşekkür ederim!!!
kanun listesi

Benim durumumda büyük bir doğaçlama değildi (base64 döküman gövdesi ile gerçekten uzun json hatları) ama
beign

1
BIDI kodunu yazan şu anki Emac’ın sağlayıcısı Eli, bunu kapatma konusunda şöyle yazıyor bidi-display-reordering: “Bir yorumum, çift ekran gösterme sırasının devre dışı bırakılmasının… ekran motorunu test edilmeyen bir duruma sokması ve tutarsızlıklara neden olabileceği yönünde. ve hatta hatalar (çünkü kodun bazı bölümleri bu değişkenin hiçbir zaman sıfır olmadığı varsayımıyla yazılmıştır). ”
Clément

18

Küçük bir jquery kopyası kullanarak bununla ilgili kısa deneyler yaptım. font-lock-modeve flycheck-modeher ikisi de yaptığı gibi, yavaşlık katkıda js2-modeve prettify-symbols-mode. line-number-modeve column-number-modeküçük etkisi oldu. Bir keresinde performans nispeten çabuk olmasına rağmen farklı modları kapatmıştım. C-h mEtkinleştirilen farklı modları devre dışı bırakmayı kullanın ve başlayın ya da sadece geçiş yapmayı deneyin fundamental-mode.

İlginçtir hexl-modeki, sütunlar oldukça kısa olmasına rağmen, dosya kullanarak herhangi bir sorun olmadan uçabiliyordum. Ne yazık ki visual-line-modegerçekten işleri yavaşlattı.

Tahminim, sözdizimi tablosunun satır sonlarında işlemeyi durdurmaktan mutlu olduğu ve her satırda bir satırda işlem yaptığı her güncellemede her şeyi yeniden doldurması gerektiğidir.


2
Flycheck'in izleyicisinde bir hata raporu açabilir misiniz? Sorunlara neden olan uzun çizgiler istemediğimizden eminim ve Emacs + Flycheck, Emacs'dan daha kötü olmamalı (ki hala oldukça kötü).
Clément

16

Http://www.emacswiki.org/emacs/OverLongLineMode dosyasını yükledim

Bu kütüphane, fundamental-modenormal modu yerine bir dosya için bir değişkenin kullanılacağı basit çizgi uzunluğu eşiklerini ayarlamanızı sağlar (yalnızca programlama modları için).

Potansiyel olarak bu satırlar boyunca bir şey varsayılan olarak Emacs'a eklenebilir, ancak bu, Emacs'in birincil sorusu için böyle bir dosyayla karşılaştığında sürünerek yavaşlayan geçici bir çözüm olabilir.

nb Bu, başlangıçta bu cevapta gönderdiğim koddaki bir gelişmedir, ancak halen devam etmekte olan bir çalışmadır. Test çok az olmuştur. Yorumlarınızı bekliyoruz.

Diğer (yanı sıra css-mode) prog-modevarsayılan olarak desteklenmek üzere onaylanmamış ana modlar için öneriler de memnuniyetle karşılanmaktadır.


1
Şimdi daha da geliştirildi ve utanmadan so-long.el :) olarak yeniden adlandırıldı (yukarıdaki bağlantı yönlendirilecek). Bununla yapılabilecek daha çok şey var, ancak olduğu gibi% 100 işlevsel ve kullanışlı.
phils

Bu gerçekten güzel bir çözüm (MELPA'da görmek isterdim), ancak Emacs örneğim one_line.json açarken hala çok yavaş. İlk önce asıl modu etkinleştirmeden önce bunun daha hızlı olacağını düşünüyorum.
Wilfred Hughes,

3
Bunu tekrar okudum ve sorudan one_line.json dosyanızı kullanarak, varsayılan-yapılandırma Emacs 25.3 ve 26.0.91'i bu dosyayı açmalarını istedikten sonra yanıt vermelerini beklemekten vazgeçtim (bir dakikadan fazla bekledikten sonra) so-long.elaktif olan config dosyayı 2 saniyeden daha kısa sürede açtı. Aslında dosyayı düzenlemek hala oldukça sorunlu (örneğin, 'sonraki satıra' geçmeye çalışmak çok uzun zaman alacaktır), ancak yine de bu, yazdığım kütüphanenin yararlılığına olan inancımı geri kazanıyor, bu yüzden yazmayı planlıyorum. GNU
ELPA'ya

1
Henüz (M) ELPA'da mı?
binki

3
Durum raporu: 1.0 sürümü so-long.el(çok sayıda iyileştirme ile birlikte) Emacs 27'nin mevcut geliştirme sürümlerine dahil edilmiştir ve yakın bir zamanda GNU ELPA aracılığıyla (Emac'ların önceki sürümleri için) kullanıma sunulacaktır.
phils,

7

Aradaki farkın sebebini bulacağınızı umuyorum font-lock. Pencerede görülebilen dosyanın alt kümesinde fontifikasyon yapılacaksa, ilk önce fontlaşma bölgesini tam anlamsal birimler içerecek şekilde genişleterek devam eder. Bunun için font-lock-extend-region-functionskoda bakınız . Bunun, bölgenin tam çizgiler içerecek şekilde genişletilmesini içermesi yaygındır. Çizgiler aşırı uzun olduğunda, bu, fontların gerçekten göründüğünden çok daha büyük bir içerik yığınında gerçekleştirilmesine neden olabilir.

Ek olarak, yeni satırların kendileri anlamsal bilgilere sahip olduğunda, bunların yokluğu bazen yazı tipi kilidi için regexp kalıplarının eşleşip eşleşmediklerini belirlemek için daha fazla taraması gerektiği anlamına gelebilir.


7

Genellikle uzun satırları kaldırırım ve etiketlere göre girinti (HTML, XML, JSON gibi).

Böyle bir işlemi mümkün kılmak için şunu ekliyorum:

(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))

Ben XML bunu için, regex satır bölünmüş: C-M-% >< RET >NL< RET !.

Emacs uzun çizgiler ayırdıktan sonra - birçok *-modeskodu tekrar girip tekrar girintiyi girebilirsiniz.

Not için: Düşük kaliteli işlemler uzun çizgiler oluştururken yavaşlama nasıl önlenir?


4

Burada bu sorun için kendi çözümümü oluşturdum: https://github.com/rakete/too-long-lines-mode

Çok uzun çizgilerden oluşan bir tamponu temel moda geçiren phils çözümünden memnun kalmadım, sözdizimi vurgulamasını ve diğer ana mod özelliklerini korumamı sağlayan bir çözüm istedim. Bu yüzden aşırı uzun çizgilerin çoğu karakterini gizlemek için bindirmeleri kullanan küçük bir mod yarattım.

Bu sorun etrafında çalışır ve temel moda geri dönmek zorunda kalmadan, çok uzun çizgileri olan tamponlarda bile amacları kullanılabilir hale getirir.


2

Emac kurulumumda, özel fontlandırmaya sahip bir modum var, yani belirlediğim yerde font-lock-defaults. Tek bir sayfa aşağı 30000 karakter satırının bir kısmını görüntülemek için 30 saniye kullanır. Bu yavaşlama, regexp geri izlemesini azaltarak giderildi. Onun yerine:

  (". * tamamlanmamış bir komutla sona erdi *" 0 font-lock-comment-face)

Bunu yap

  ("^. \ {1,80 \} eksik bir komutla sona erdi *" 0 font-lock-comment-face)

Bu, özellikle font-lock-defaultseşleştirme ile ilgili olmayan veya regexp eşleşmeyen bir sorunun cevabı değildir .
Drew

1
İdeal regex Küçüktür @Drew edilir olsa ... uzun hatlarda yavaş font-lock yapma
wasamasa

1
@wasamasa: Evet. Sorunun kendisi çok geniş, IMO. Uzun çizgiler söz konusu olduğunda Emacs'i yavaşlatabilecek birçok şey var (ve hangi eylemler için?).
Drew,

3
Sorunun geniş olduğunu sanmıyorum ("neden uzun çizgiler Emac'ları yavaşlatıyor")? Ben de cevabın soruyu ele aldığını sanmıyorum (" olası bir sebep suboptimal regexps"). Diğer cevaplar diğer nedenleri de ele alabilir. Uzun satırlı bir dosyayı açmak, bir konuyu genişletmek değildir, çünkü bu, çeşitli nedenlerden dolayı sorunlu olabilir, bazen bu tür dosyalara sahipsiniz ve tercihen Emacs kullanarak bunlara bakmak zorundasınız.
tarsius

1

Kabuk modu tamponlarımda (Mx kabuğu), sed -r 's/(.{2000}).*/\1/' -uuzun çizgilerden kaçınmak için kendimi borular buluyorum .


Bu, sorunun ikinci bölümünü cevaplıyor: performansın nasıl iyileştirileceği. İlk kısmı ele almıyor (ki sorun değil): " Emacs neden uzun çizgilerle bu kadar düşük bir performansa sahip ?"
Drew

0

dired-modeUzun satırlı büyük dosyaları açmak için aşağıdaki işlevi kullanıyorum :

(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

İşte emacs-devel'den alınan bir geçici çözüm :

(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 itibariyle Emacs'ta bu longlines-mode, eskimiş olarak işaretlendi visual-line-mode.
Alexander I.Grafov

Ancak iki özellik perde arkasında çok farklı şeyler visual-line-modeyapıyor ve söz konusu konuya yardımcı longlines-modeolmuyor. Bu nedenle, longlines.el 'in itiraz edilmemiş bir duruma geri yüklenmesini bekliyorum.
phils,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.