技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

PlayFramework2.0x でファイルをストリーム転送する

実装そのものは大した問題ではなく、

http://scala.playframework.org/documentation/2.0.4/ScalaStream

なわけなのだが、どれだけ速度が出るものなのか確認してみる。

設定をこう書いて、

directory.path="C:/Users/XXXX/Pictures"
directory.extension="jpg"

コードをこう書いて

  def loadFile(fileName:String) = Action {
    Logger.apply("application").logger.debug("file : %s".format(fileName))
    val config = Play.current.configuration
    val firectoryPath = config.getString("directory.path").get
    val file = new File("%s/%s".format(firectoryPath, fileName))
    val fileContent: Enumerator[Array[Byte]] = Enumerator.fromFile(file)

    SimpleResult(
      header = ResponseHeader(200),
      body = fileContent
    )
  }

URL をざくっと書く

GET     /file/:filename             controllers.Application.loadFile(filename:String)

ファイルをWeb経由で落とすだけならこれでOK。よろしいでは転送速度だ。


で、検証しようかと思ったのだが、ローカルエリア意味がねえ、、、、メインマシンのHDアクセス速度がネットワークアダプタの限界速度値を上回ってる(普通はそうだわな?)ので、この条件でアクセスしてもアダプタ性能が出るだけだ、、、、。
Javaのファイルストリームアクセス速度を測るしかないか。

一応 302kb の画像に下記の処理をループし、10回計測する。

    val firectoryPath = "C:/Users/azalea/Pictures/055.jpg"
    val file = new File(firectoryPath)
    val stream = new FileInputStream(file)
    val reader = new InputStreamReader(stream)
    val buffer:Array[Char] = Array.fill(10)(0)
    val start = System.currentTimeMillis();

    var length = 0
    while (length > -1)
      length = reader.read(buffer)

    val end = System.currentTimeMillis();

    reader.close()
    stream.close()

    println("ExecutedTime: " + (end - start))

結果が

ExecutedTime: 27
ExecutedTime: 26
ExecutedTime: 24
ExecutedTime: 25
ExecutedTime: 24
ExecutedTime: 23
ExecutedTime: 24
ExecutedTime: 24
ExecutedTime: 24
ExecutedTime: 24

で、バッファサイズに影響を受けるという情報があるので、試しにやってみる。

val buffer:Array[Char] = Array.fill(300000)(0)

という感じで

ExecutedTime: 20
ExecutedTime: 21
ExecutedTime: 20
ExecutedTime: 21
ExecutedTime: 20
ExecutedTime: 20
ExecutedTime: 20
ExecutedTime: 20
ExecutedTime: 20
ExecutedTime: 19

この程度のサイズじゃ微妙か、、、、でも意味がないわけでは無さそう。
ということで、3.6MBのファイルで比較

100 バイトアクセス

ExecutedTime: 132
ExecutedTime: 131
ExecutedTime: 124
ExecutedTime: 125
ExecutedTime: 128
ExecutedTime: 123
ExecutedTime: 125
ExecutedTime: 123
ExecutedTime: 123
ExecutedTime: 126

300K バイトアクセス

ExecutedTime: 91
ExecutedTime: 90
ExecutedTime: 91
ExecutedTime: 91
ExecutedTime: 91
ExecutedTime: 90
ExecutedTime: 91
ExecutedTime: 91
ExecutedTime: 91
ExecutedTime: 91

おおぅバッファサイズを弄るのには意味がありそう。
で、Play でそれを設定する場合は第二匹数にサイズを指定する。
今日日サーバのメモリ単価は安かろうし、速度上げるならこれで 40% 程度改善が見込めると、、、、マシンによるんだろうけど。

val fileContent: Enumerator[Array[Byte]] = Enumerator.fromFile(file, 300000)