5

Webサーバーで使用するサンプルコードを変更してきました。これにより、サーバーとクライアントの両方でdartを実行できます。しかし、Webサーバーのパフォーマンスを確認したいと思ったので、クラッシュすることを除けば、ほとんど感銘を受けました。私はUbuntuの「siege」パッケージを使用して、少数のURLを使用してWebサイトへの大量のトラフィックを生成しています。

1秒あたり1000トランザクションの少し北を配信しているのを確認しました。これは私にとっては非常に許容範囲ですが、実行時間が2〜3分になると、クラッシュまたはハングします(new_gen_heap_sizeを増やすと)。

#import('dart:io');

class FCServer {

String basePath;

void send404(HttpResponse response)
{
    response.statusCode = HttpStatus.NOT_FOUND;
    response.outputStream.close();
}

void handleRequest(HttpRequest request, HttpResponse response)
{
  final String path = request.path == '/' ? '/index.html' : request.path;
  final File file = new File('${basePath}${path}');
  file.exists().then((bool found) {
      if (found)
      {
          file.fullPath().then((String fullPath) {
              if (!fullPath.startsWith(basePath))
              {
                  send404(response);
              }
              else
              {
                  //print("delivering $fullPath");
                  response.headers.add("Cache-Control", "max-age=3600");
                  //file.openInputStream().pipe(response.outputStream);
                  var file = new File("$fullPath");
                  //response.headers.set(HttpHeaders.CONTENT_TYPE, "$contentType; charset=UTF-8");
                  response.outputStream.write(file.readAsBytesSync());
                  response.outputStream.close();
              }
         });
        }
        else
        {
            send404(response);
        }
    }); 
}

void startServer(String basePath)
{
    this.basePath = basePath;
    var server = new HttpServer();
    print("Starting server with basePath: $basePath");
    server.listen('192.168.0.14', 8080);
    server.listen('127.0.0.1', 8080);
    server.defaultRequestHandler = handleRequest;
}
}

FCServer webServe;
main()
{
    // Compute base path for the request based on the location of the
    // script and then start the server.
    webServe = new FCServer();
    File script = new File(new Options().script);
    script.directory().then((Directory d) {
        webServe.startServer(d.path);
    });
}

Dartが終了する前に出力するエラーは次のとおりです。

Exhausted heap space, trying to allocate 128096 bytes.
Exhausted heap space, trying to allocate 112 bytes.
Exception 'Instance of 'OutOfMemoryException'' thrown:
Exiting the process

これは、どこかにメモリリークがあることを意味しますか?または誰かが何が起こっているのか説明できますか?

編集:new_gen_heap_sizeを1024に増やすと、しばらくするとハングし、リクエストが着信しているかどうかに関係なく、単一のスレッドが100%になります。この時点で、前述のヒープサイズで実行した後、RAMは最大1.5 GBになるため、ガベージコレクターがいわばバケツを蹴ったと思います。

編集2:初期化時に4バイトで構成されるリストを作成するようにコードを変更しました。その後、リクエストが行われるたびに、そのリストを応答に書き込み、応答を閉じます。メモリ使用量は依然として急速に増加しており、Dart内のより深い問題を示しています。これにより、Dartを本格的なプロジェクトに使用することにうんざりします。

4

1 に答える 1

4

「file.openInputStream()。pipe(response.outputStream);」をコメントアウトしたのはなぜですか。そしてそれを"response.outputStream.write(file.readAsBytesSync());"に置き換えますか?これには3つの問題があります。

  • 読み取りが完了しても、ファイルは閉じられません。
  • 非同期ではありません。
  • クライアントにストリーミングするのではなく、すべてのバイトを同時に読み取ります。

非常に大きなファイルを提供していて、同時にリクエストが非常に多い場合は、そのファイルのコピーがメモリに大量に存在します。

「file.openInputStream()。pipe(response.outputStream);」を使用しますか 問題を解決しますか?

「response.outputStream.write(file.readAsBytesSync());」と確信しています。問題です。また、.writeはバイトをすぐには書き込まないことに注意してください。書き込まれるようにそれらをバッファリングします。したがって、ファイル全体のコピーがバッファリングされて書き込まれます。

更新:Mads Agerは、それがメモリリークであることを確認し、すでに修正を提出しています。これが彼が提出したバグです。

于 2012-11-02T17:44:17.263 に答える