劣ったプロセスが長い行を生成するとき、スローダウンを防ぐ方法は?


14

EmacsをGeiserで使用して、Schemeコードをハックします。REPLで遊んでいると、多くの場合、すべてが1行で出力される式を評価することあります。

たとえば、SRFI-41(ストリーム)で遊んで、大きなファイルから文字ストリームを作成しました。次に、ストリームを強制し、Geiserはファイルのコンテンツ全体を文字ストリームとしてバッファにバーフしました。ほとんどすぐに、私は保持どのくらいの出力ラインに追加、より多くの文字などの停止、そしてどんなににEmacsの地面が押すC-gC-c C-c、私は、Emacs(またはガイザー)の停止を行うことができませんでした。

Emacsは私の入力を完全に無視するようになり、この巨大な文字ストリームをすべて1行で無反応のGeiser REPLバッファーに出力することを優先する必要があると考え、Emacsセッション全体を中断しました。

Emacsセッションを破壊的な好奇心から守るためにできることはありますか?(とにかく非常に長い行を表示するときにEmacsが非常に遅くなるのはなぜですか?)



2
さて、私の質問は長い行自体を表示することではありません。そもそもこのようなことを避ける方法を知りたいのです(Emacsは下位プロセスから行を読み取りますが、修正可能なファイルからは読み取りません)。そしてそれは、単一の動的バッファへのEmacsの献身のためにEmacsセッションを失うのを防ぐ方法についてです。
レカド14

「まあ、私の質問は長い行を表示することではありません」それから、タイトルを変更する必要があるかもしれません。おそらく、下位プロセスの出力をフィルタリングし、一定量の文字の後に新しい行を追加したいでしょうか?
ナニー14

しかし、実際には、これは長い行とはほとんど関係ありません。例えば、同様の(しかしていないことが恐ろしい)効果。実際、emacsに一時停止を与えるのはテキストの量だけです。yesansi-term
PythonNut 14

バッファへのテキストの挿入は非常に高速です。再表示操作により、実際よりも遅く表示されます。正直なところ、yesVTEターミナルエミュレーターで実行すると、すべてのCPUコアが最大限に使用されるため、例として使用しません。
wasamasa 14

回答:


12

すでにコメントで回答したように、Emacsが長い行の再表示で非常に遅くなることはよく知られている問題です。それを修正することは非常に良いことですが、正しく実行するには多くの考えが必要です。このドキュメントのセクション6.3に基づいてどのように達成できるのか考えています (基本的に、現在のバッファに視覚的な行情報を保存し、空白の挿入、プロパティの表示、ウィンドウの変更などで更新してから、その情報を使用します常にスキャンすることを避けるためにコードを再表示します)が、Cの内部構造を十分に理解していないため、それを実行できません。

ただし、回避策があります。最も明白なものは、表示関連のパラメーターの調整(たとえば、グラフィカルなEmacsインスタンスでの視覚的な行の切り捨ての有効化、非グラフィカルなEmacsを使用した自動化、Bidi機能の無効化など)と、ファイルコンテンツの前処理です。あまり目立たないのは、ファイルを実際に後処理することです。実際に行を切り詰めたり、行が実際よりも短く見えるようにするテキストプロパティを追加したりします。これをより興味深い答えに変えるために、comint派生オプションでのみ機能する以前のオプションのかなりいハックを紹介します。

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?$")
         (shortened-text (replace-regexp-in-string regexp "\\1" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

これはmy-comint-shorten-long-lines、多くの行で構成されている可能性がある文字列を受け取り、その中の任意の行を80文字以上の長さで置き換える関数を定義します。フックとして使用すると、 表示される前にcomint-preoutput-filter-functionsすべてのcomint出力がフィルタリングされます。

ただし、このハックの表現にはかなり深刻な弱点があります。基本的なフォント化が行われているモード(などM-x ielm)では、文字列の一部である行を喜んで切り取り、次の引用符が文字列として表示されるまですべてをフォント化します!それは私たちが望んでいるものではなく、もう少し正規表現を習得することで修正できます(ただし、おそらくPythonのような言語のREPL内で壊れるでしょう)。ここで、短縮出力も強調表示しましょう。

(defun my-comint-shorten-long-lines (text)
  (let* ((regexp "^\\(.\\{80\\}\\).*?\\(\"?\\)$")
         (shortened-text (replace-regexp-in-string regexp "\\1\\2" text)))
    (if (string= shortened-text text)
        text
      (propertize shortened-text 'font-lock-face 'shadow 'help-echo text))))

(add-hook 'comint-preoutput-filter-functions 'my-comint-shorten-long-lines)

それは少し良いですが、それでもstillいです。find /inのようなものの出力にカーソルを合わせるのM-x shellは魅力的ではありません(すべての出力ではなく、短縮されていない行のみを表示するのが理想です)。さらに、入ってくるテキストがバッチに変換されないことも保証されていません。このすべては、一時バッファーで処理ステップを実行することで悲鳴を上げますが、演習(または潜在的なブログ投稿として作成者)として読者に残されます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.