4

Perl readdir を使用してファイル リストを取得していますが、ディレクトリには 250,000 を超えるファイルが含まれているため、readdir の実行に長時間 (4 分以上) かかり、80MB を超える RAM を使用します。これは 5 分ごとに繰り返されるジョブであることを意図していたため、この遅延時間は許容できません。

詳細: 別のジョブが、スキャン中のディレクトリを (1 日に 1 回) 埋めます。この Perl スクリプトは、ファイルの処理を担当します。スクリプトの反復ごとにファイル数が指定されており、現在は実行ごとに 1000 です。Perl スクリプトは 5 分ごとに実行され、(該当する場合) 最大 1000 個のファイルを処理します。Perl が複雑なワークフローをトリガーするデータベースにデータをプッシュする際に、ダウン ストリーム処理を維持できるようにすることを目的としたファイル数の制限。

ディレクトリからファイル名を取得する別の方法はありますか?理想的には 1000 (変数で設定) に制限すると、このスクリプトの速度が大幅に向上しますか?

4

6 に答える 6

9

readdir数分と 80 MB かかると言うとき、正確にはどういう意味ですか? その特定のコード行を表示できますか? readdirスカラーまたはリストのコンテキストで使用していますか?

あなたはこのようなことをしていますか:

foreach my $file ( readdir($dir) ) { 
   #do stuff here
}

その場合は、ディレクトリ リスト全体をメモリに読み込んでいます。長い時間と多くのメモリを必要とするのも不思議ではありません。

この投稿の残りの部分では、これが問題であると想定していますreaddir。リスト コンテキストで使用していない場合は、残りの部分を無視してください。

これを修正するには、while ループを使用readdirし、スカラー コンテキストで使用します。

while ( 
    defined( my $file = readdir $dir )
 ) {

    # do stuff.

}

これで、一度に 1 つの項目だけを読むことができます。カウンターを追加して、処理するファイルの数を追跡することもできます。

于 2009-04-09T22:34:44.767 に答える
7

解決策は、おそらくもう一方の端にあります。ディレクトリを満たすスクリプトで...

これらすべてのファイルを格納する樹木を作成して、それぞれに管理可能な数のファイルを含む多数のディレクトリを作成してみませんか?

「mynicefile.txt」を作成する代わりに、「m/my/mynicefile」などを作成しないのはなぜですか?

あなたのファイルシステムはそれを感謝します(特に、空のディレクトリを使い終わったときにそれらを削除する場合).

于 2009-04-09T21:13:11.640 に答える
2

これはあなたの質問に対する正確な答えではありませんが、同じディレクトリに多くのファイルがあることは、全体的な速度にとってあまり良いことではないと思います(ファイルシステムが追加および削除操作を処理する速度を含め、単にあなたのようにリストするだけではありません)見たことがある)。

この設計上の問題の解決策は、ファイル名の最初の文字ごとにサブディレクトリを作成し、その文字で始まるすべてのファイルをそのディレクトリ内に作成することです。必要に応じて、2 番目、3 番目などの文字に戻ります。

おそらく、5 回の操作で明確な速度の向上が見られるでしょう。

于 2009-04-09T21:13:18.520 に答える
2

あなたは、zipファイルを解凍することでコンテンツがそこに到達すると言っています。1 つのディレクトリで 250k のファイルを作成/使用する代わりに、zip ファイルで作業しないのはなぜですか?

基本的に - 高速化するために、perl で特定のものは必要ありませんが、ファイルシステム レベルで必要です。ディレクトリ内の 250k ファイルを操作する必要があると 100% 確信している場合 (このようなものが必要になる状況は想像できません)、それを処理するためのより優れたファイルシステムを見つけるよりもはるかに優れています。それをより速くスキャンするperlの「魔法の」モジュール。

于 2009-04-09T21:33:03.887 に答える
1

readdir を高速化することはできませんが、ディレクトリを監視するタスクを高速化できます。OS に更新を要求できます。たとえば、Linux には inotify があります。使い方については以下の記事です。

http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html?ca=drs-

Perl から Inotify を使用できます。

http://metacpan.org/pod/Linux::Inotify2

違いは、cron によって開始されるスクリプトではなく、実行時間の長いアプリが 1 つあることです。アプリでは、(inotify によって提供される) 新しいファイルのキューを保持します。次に、タイマーを 5 分ごとに設定し、1000 個のアイテムを処理します。その後、制御がイベント ループに戻り、5 分以内に起動してさらに 1000 個のアイテムを処理するか、inotify がさらにファイルを送信してキューに追加します。

(ところで、タイマーを処理するにはイベントループが必要です。EVをお勧めします。)

于 2009-04-10T04:13:02.427 に答える