11

EF ベースのアプリケーションの起動時間を短縮しようとしていますが、単一エンティティ コンテキストであっても、最初の読み取りにかかる時間を 7 秒未満に短縮できないことがわかりました。特に奇妙なのは、今回はコンテキスト タイプ固有ではないことです。

これらの遅い時間の原因や、物事をより速く実行する方法を誰かが説明できますか?

完全なサンプル コードは次のとおりです。

私のデータベースには、主キー列 AptId を持つ se_stores という名前のテーブルがあります。

    // a sample entity class
public class Apartment
{
    public int AptId { get; set; }
}

    // two identical DbContexts        

public class MyDbContext1 : DbContext
{
    public MyDbContext1(string connectionString) : base(connectionString)
    {           
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MyDbContext1>(null);

        var config = new EntityTypeConfiguration<Apartment>();
        config.HasKey(a => a.AptId).ToTable("se_stores");
        modelBuilder.Configurations.Add(config);

        base.OnModelCreating(modelBuilder);
    }
}

public class MyDbContext2 : DbContext
{
    public MyDbContext2(string connectionString)
        : base(connectionString)
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer<MyDbContext2>(null);

        var config = new EntityTypeConfiguration<Apartment>();
        config.HasKey(a => a.AptId).ToTable("apartments");
        modelBuilder.Configurations.Add(config);

        base.OnModelCreating(modelBuilder);
    }
}

    // finally, I run this code using NUnit:

var start = DateTime.Now;
var apt1 = new MyDbContext1(connectionString).Set<Apartment>().FirstOrDefault();
var t1 = DateTime.Now - start;
start = DateTime.Now;
var apt2 = new MyDbContext2(connectionString).Set<Apartment>().FirstOrDefault();
var t2 = DateTime.Now - start;
Console.WriteLine(t1.TotalSeconds + ", " + t2.TotalSeconds);

次のようなものが確実に出力されます: 7.5277527, 0.060006。最初に MyDbContext2 を使用するようにテストを切り替えると、同じ結果が得られます (したがって、最初に初期化された DbContext に対して発生します)。また、EF パワー ツールを使用してビューを事前に生成しようとしました。これにより、最初のコンテキストの時間が約 6.8 秒に短縮され、小さな勝利に過ぎませんでした。

DateTime.Now がひどいプロファイリング方法であることは理解していますが、dotTrace を使用している間、これらの結果は維持されています。また、一部のコードを初めて実行すると JITing コストが発生することも認識していますが、7 秒という値は、その原因とするには高すぎるようです。

VS 2010 で EF 4.3.1 と .NET 4 を使用しています。

よろしくお願いします。

編集:SQL接続を開くと問題が発生する可能性があることが示唆されました。

  1. 最初に、生の SqlConnection を使用してランダム クエリを実行し、同じ接続文字列でコマンドを作成してみました。これには 1 秒かかり、DbContext の初期化時間には影響しませんでした。
  2. 次に、接続文字列を使用して SqlConnection を作成し、それを接続を受け取る DbContext のコンストラクターに渡してみました。contextOwnsConnection=false を渡しました。これも、DbContext の初期化時間に違いはありませんでした。
  3. 最後に、同じ資格情報と接続文字列オプションを使用して、管理スタジオ経由で接続を試みました。これはほぼ瞬時でした。
  4. dotTrace プロファイルでは、SqlConnectionFactory.CreateConnection(connectionString) が 0.7 秒かかると測定されます。これは生の SQL 時間と一致しています。

編集: 遅延が接続ごとに発生したのか、1 回だけだったのかを知りたいと思いました。したがって、 MyDbContext1 と MyDbContext2 を異なるサーバー上のまったく異なるデータベースに接続しようとしました。これは、最初に接続されたデータベースに関係なく、違いはありませんでした。最初の DbContext の使用には約 7 秒かかりましたが、2 番目のコンテキストの使用は非常に高速です。

4

2 に答える 2

8

あなたが書いたコードを独自のプロジェクトに入れた後、プロジェクトのプラットフォーム ターゲットが EF フレームワークの起動時間に大きな影響を与えることがわかりました。

x64 プラットフォームをターゲットにすると、あなたと同様の結果が得られました (最初の DbContext で 7 秒のスピンアップ、2 番目の DbContext で 1 秒未満)。x86 をターゲットにすると、最初の DbContext のスピンアップ時間が約 4 秒短縮されて 3.34633 秒になり、2 番目の DbContext には x64 の場合と同様の時間がかかります。

なぜこれが起こるのかはわかりませんが、Entity Framework がさまざまな環境で自分自身を初期化する方法に関係しているに違いありません。私はそれについて別の質問をここに投稿しました。

于 2012-09-25T14:12:29.100 に答える
1

いくつかのコメントによると、2番目が非常に高速に実行される理由は、接続マネージャーが接続をキャッシュしているためです。そのため、最初の接続を取得することが問題であると私は信じています。

試すこと:

  1. 名前の代わりに db サーバーの IP アドレスを使用するように接続文字列を変更します。

  2. まったく同じ資格情報とメカニズムを使用して、SQL Management Studio を使用してデータベース サーバーに接続します。7秒かかるマシンからそうしてください。しばらく時間がかかると仮定して、どのプロトコルが使用されているかを調査し、必要なプロトコルがリストの最初にあることを確認してください。

  3. マシンにネットワーク アナライザを配置して、その動作を観察します。

于 2012-09-24T22:36:26.507 に答える