2009-04-13 8 views
12

Common Lispイメージ内のWebサーバーなど、長時間実行しているアプリケーションをホストしている場合は、ガベージコレクタを管理するためにどのような戦略を使用する必要がありますか?長年走っているCommon Lispアプリケーションでは、ガベージを管理するためにどのような戦略を使用すべきですか?

ガベージコレクタは、デフォルトでヒープを並べ替えるのに長い時間を費やすことができますが、私は予測できない時代だとします。これは、私が欲しくない方法で特定のブラウザ要求に影響を与える可能性があります。

これを制御するCommon Lispにはメソッドがありますか?おそらくそれを「少しずつ」の仕方で働くように励ますことによって?

+0

どのlisp実装を使用していますか? – Zifre

+0

"私は推測しています"と言えば、プロファイリングをしなくても最適化をしようとしているようです。あなたの環境で修正が必要な特定の問題が発生していますか? – Ken

+0

私はまだ現れていない問題について自分自身に説明するプロセスを開始しています。 Webサービスで使用されているGC言語の量を考えると、これは主に解決された問題であると私は考えています。 –

答えて

24

いくつかのLisp実装は、優れたガベージコレクタを備えています。特別な問題は、Lispアプリケーションがしばしば小さなオブジェクト(conses、...)の高い割り当て率を持つことです。

考慮すべき点がいくつかあります。

  • Precise vs. Conservative GC。私はLispの保守的なGC(Boehmなど)の巨大なファンではありません。保守的なGCの問題は、すべてのゴミが見つからないということです。これは、長時間実行されているプログラムでは問題になる可能性があり、フラグメンテーションにつながり、未使用のメモリを再利用することはありません。正確なGCはLispデータのタグ情報を使用しており、すべてのオブジェクトのすべてのデータ型を識別できます。保守的なGCは、タグ付きデータを使用しないプログラミング言語の実装(C++、...)のために考案されました。

  • コピーGC、圧縮GC。長時間実行するLispsでメモリの断片化を防ぐために、オブジェクトを圧縮してローカライズするGCが便利です。ハッシュテーブルを再ハッシュしなければならない場合(場所が変更されるため)、時には問題が発生します。コピーGCはより多くのメモリを必要とする可能性があります(メモリのfromとaのスペースがあるため)。しかし、GCがオブジェクトをあるメモリ空間から別のメモリ空間にコピーすると、自動的にコンパクトになります。より高度なGC(Lispマシンのような)は、オブジェクトをソートし、同じタイプのオブジェクトを互いに近くに割り当てることができます - これがオブジェクトへのアクセスを高速化すると仮定します。

  • 一時的GC。これは、主メモリ内で排他的に実行される第1のGCステージが存在し、メモリ管理ユニットから何らかのサポートを得て、変更されたメモリ領域を特定することを意味する。メインメモリのスキャンは仮想メモリのスキャンより高​​速であり、変更されたメモリ領域のスキャンだけで作業量がさらに減少します。たくさんのオブジェクトが割り当てられ、すばやくガベージに変わると、GCの一時停止が非常に短くなります。

  • 世代GC。通常、今日のGCは世代的なものです。複数の世代が存在し、いくつかのGCで生存するオブジェクトは古い世代に昇格されます。通常、第1世代のみがGCedされます。

  • チューニング。 LispWorksとAllegro CLのGCには、多くのチューニングノブがあります。特に長時間実行されるアプリケーションの場合は、マニュアルを読んで、世代数やサイズなどを調整するのが理にかなっています。

  • 仮想メモリ。仮想メモリ上のGCは通常非常に遅いです。可能であれば、マシンにRAMを追加しないでください。

  • 手動メモリ管理。たとえば、CL-HTTP Webサーバーは、リソースを使用して手動でメモリ管理を行います。これらは、事前に割り当てられたオブジェクトのプールであり、非常に迅速に再初期化できます。 Lispマシンはこれをたくさん使っていました。それらの典型的な用途は、ストリームのための読み出しバッファにある。すべての読み取り操作で新しい文字列を作成するのではなく、再利用可能なバッファーを使用すると便利です。

  • スタック割り当て。いくつかのCommon Lispでは、いくつかのデータのスタック割り当てが許可されます。ブロックを残すと自動的にメモリが解放されます。これは、ブロックを離れるときにメモリがもはや参照されないことを前提としています。

  • 同時GC。通常のCommon Lisp実装では、並行GCと同時Lispスレッドのサポートはありません。いくつかの実装では、同時Lispスレッドがありますが、GCは動作中にそれらをすべて停止します。 GCをプロファイリングするステップとを含む。割り当てがどこで行われているかわからない場合は、プロファイリング情報を使用してGCを調べる必要があります。

Lispにメインメモリで実行される正確な世代GCがある場合、長いポーズでは問題が発生しません。例えば、Clozure CL(無料のCommon Lisp実装)は、非常に良いGC実装を持っています。仮想メモリ内のメモリの断片化やガベージコレクションを回避する必要があります。必要であれば、より多くのメインメモリを持つ64ビットLisp実装を使用してください。

ポインタ:あなたはそのLispWorksドキュメントから見ることができます

とAllegro CLにはチューニング用のノブがたくさんありますGC。

Common Lispには実装環境を扱う関数がいくつかあります。 (ROOM)は、メモリ使用量の概要を示す関数です。 (ROOM t)は、より詳細な情報を提供しています(ここLispWorks):

CL-USER 2 > (room t) 
Generation 0: Total Size 1823K, Allocated 1090K, Free 725K 
      Segment 2008AAB8: Total Size 507K, Allocated 361K, Free 142K 
        minimum free space 64K, 
         Awaiting promotion = 0K, sweeps before promotion =10 
      Segment 217E7050: Total Size 1315K, Allocated 729K, Free 582K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =2 
Generation 1: Total Size 1397K, Allocated 513K, Free 871K 
      Segment 20CB9A50: Total Size 68K, Allocated 48K, Free 15K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =4 
      Segment 216D7050: Total Size 1088K, Allocated 331K, Free 752K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =4 
      Segment 2004E4F8: Total Size 241K, Allocated 133K, Free 103K 
        minimum free space 0K, static 
Generation 2: Total Size 2884K, Allocated 1290K, Free 1585K 
      Segment 21417050: Total Size 2816K, Allocated 1227K, Free 1584K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =4 
      Segment 20DA5DA0: Total Size 68K, Allocated 62K, Free 1K 
        minimum free space 117K, 
         Awaiting promotion = 0K, sweeps before promotion =4 
Generation 3: Total Size 19373K, Allocated 19232K, Free 128K 
      Segment 20109A50: Total Size 11968K, Allocated 11963K, Free 0K 
        minimum free space 3K, 
         Awaiting promotion = 0K, sweeps before promotion =10 
      Segment 20DB6E18: Total Size 6528K, Allocated 6396K, Free 128K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =10 
      Segment 20CCAAC8: Total Size 876K, Allocated 872K, Free 0K 
        minimum free space 0K, 
         Awaiting promotion = 0K, sweeps before promotion =10 

Total Size 25792K, Allocated 22127K, Free 3310K 
+0

私はあなたのタグ使用の記述が完全に正しいとは思わない。 正確なGCは実際にオブジェクトのタグを(不正確であるように)見てクリーンアップする方法を決定しますが、まずレジスタの内容がオブジェクトポインタか即値かを知る必要があります。この後者の操作は、不正確なGCと正確なものを区別します。 – skypher

+0

即時オブジェクト(数字、文字、...)と非即時オブジェクト(配列には配列、構造体、文字列などのポインタが格納されています)の配列をとります。GCは、あるものが数値であり、もう1つが(構造に対する)ポインタであることをどのように知っていますか? Conservative GCは、タグ付きオブジェクトがないCやC++などの言語用に開発されました。 GCはヒューリスティックに何がポインタであるかを決定します。 –

+0

これはCのようなタグなし言語用に開発されているかもしれませんが、今日のLisp環境でも使用されています。たとえば、CMUCLやSBCLは、x86のようなレジスタが貧弱なアーキテクチャでは保守的なGCを使用します:http://sbcl-internals.cliki。ネット/ GENCGC – Ken

2

ガベージコレクションは、初期の段階から長い道のりを歩んでおり、予測できないほど長い待ち時間を避けるために多くの作業が行われています。最近の実装では、それらは過去のものだと思います。

ただし、ガベージコレクションの詳細は実装によって異なります。そこには高品質なLisp実装がたくさんあるわけではないので、ガベージコレクションに関するドキュメントを調べるのは難しいことではありません。

関連する問題