2011-01-10 11 views
6

私は数日間、イベントマシンのエコーサーバー以外の例をいくつか見つけましたが、何もないようです。ファイルへの書き込みRuby Eventmachineでファイルを書き込む方法(大)

require 'rubygems' 
require 'tempfile' 
require 'eventmachine' 

module ExampleServer 

    def receive_data(data) 
    f = Tempfile.new('random') 
    f.write(data) 
    ensure 
    f.close 
    end 

end 

EventMachine::run { 
    EventMachine::start_server "127.0.0.1", 8081, ExampleServer 
    puts 'running example server on 8081' 
} 

は、原子炉を阻止するだろうが、私はそれを「Eventmachineスタイル」を実行する方法を得ることはありません:のは、私はファイルを受け入れ、一時ファイルに書き込み、サーバーを書きたいとしましょう。チャンク内のデータを読み込み、各チャンクをEm.next_tickブロック内のディスクに書き込む必要がありますか?任意の助け

おかげ アンドレアス

docsから

答えて

1

、あなたがちょうどあなたが指摘するように、それが有効ではないかもしれないが、オプションがFile.writeを使用するようです(ファイルをattachする必要があると思われます/ ie blocking ...)とsend_dataです。

私はあなたがブロック/ EMとIOを非ブロック:(元のデータが与えられ

がソケットで混在させないと考えていたが、私はそれがEventMachineによって処理されますね。おそらく、

質問google group ...

〜クリス・

+0

クリス、あなたの答えに感謝します。 [この回答](http://stackoverflow.com/questions/2749503/what-is-the-best-way-to-read-files-in-an-eventmachine-based-app)tmm1は、ドキュメントと競合します言う(または私はどちらかと誤解する)。基本的に私は非常に単純なファイル転送(ソケットからの読み取りとディスクへの書き込み)をやろうとしています... – Andreas

0

のためにこれが(私は効率的にファイルを読み取る方法を知りたいと思った)What is the best way to read files in an EventMachine-based app?と非常によく似ています。そう、任意の非ブロックファイルのAPIがあるように思えません。 thあなたができる最善の方法は、next_tickで短いバーストを書くか、別のスレッドで実行するように書き込みを延期することです(しかし、その解決策がどのように優れているかは分かりません)。

1

残念ながら、ファイルは選択されたインターフェイスにうまく反応しません。 IO#writeよりも効率的なものが必要な場合は、EIOを使用できます。

EIOは実際には反応器を軽くブロック解除して、ちょっとしたバッファリングを提供します。特定の待ち時間が問題である場合、またはディスクが実際に遅い場合は、参考になる可能性があります。他のほとんどのケースでは、おそらくほんの少しの努力のために少しの利点です。

3

2つの回答:

レイジー回答:ブロッキング書き込みを使用してください。 EMは、すでに巨大な文字列ではなく、個別のデータ群を手渡しています。したがって、あなたの実装例はちょっとだけかもしれません。 EMがあなたを手渡すすべてのチャンクに対して新しい一時ファイルを作成してもよろしいですか?ただし、サンプルコードが意図したとおりに動作していることを前提にして説明します。

怠け者のアプローチは書き込み先のデバイスによって異なりますが、複数の大きなストリームを同時にディスクに書き込もうとすると、大きなボトルネックになり、イベントが発生するという利点がなくなりますとにかくベースのサーバーです。ディスクのシークをやり遂げると、IOパフォーマンスが低下し、サーバーのパフォーマンスも低下します。一度に多くのことを処理するのは大丈夫ですが、ブロックデバイスとIOスケジューリングを開始すると、何をしていてもパフォーマンスのボトルネックが発生します。

しかし、私は他の非IOの重いリクエストに対する応答時間を短くしたいと同時に、ディスクへの長い書き込みをしたいと思うかもしれません。だから、おそらく良い答え:

deferを使用してください。

require 'rubygems' 
require 'tempfile' 
require 'eventmachine' 

module ExampleServer 

    def receive_data(data) 
    operation = proc do 
     begin 
     f = Tempfile.new('random') 
     f.write(data) 
     ensure 
     f.close 
     end 
    end 

    callback = proc do 
     puts "I wrote a file!" 
    end 

    EM.defer(operation, callback) 
    end 

end 

EventMachine::run { 
    EventMachine::start_server "127.0.0.1", 8081, ExampleServer 
    puts 'running example server on 8081' 
} 

はい、これはスレッドを使用します。この場合、実際には悪いことではありません。つまり、スレッド間の同期について心配する必要はありません.MEMはこれを処理するのに十分優れているからです。応答が必要な場合は、コールバックを使用します。コールバックは、ワーカースレッドが完了したときにメインリアクタスレッドで実行されます。また、GILはここでIOブロッキングを扱っており、CPUの同時実行性を達成しようとしていないため、このケースでは何の問題もありません。

しかし、すべてを同じファイルに書き込もうとした場合は、スレッドが同じファイルに同時に書き込みを試みる可能性があるため、同期の問題が発生するため、遅延に注意する必要があります。

関連する問題