2012-05-26 15 views
18

Uygulama test uygulamasına sahibim. Hangi mssql db içinde db nesnesine akıcı nhibernate haritalama kullanır. İnce ayar dinlemeyi öğrenmek istediğimden beri. mvc3 uygulamaları, bu uygulamayı kullanıyorum. 10 enum özelliği ve bir dizgi özelliği ile sadece basit bir varlığa sahip olan test amaçları için. Yani, gerçekten hafif dalga, henüz nhibernate profiler göre başlangıç ​​zamanı 4.37 sn. Birkaç satırda işaretli/işaretlenmemiş mülk olan bir varlığı oluşturmak için gerçekten yavaş olan.nhibernate oturumunun fabrika ayarlanması, webApp başlangıç ​​zamanı gerçekten yavaş

Kod aşağıdaki gibidir. Domain.SessionProvider.cs

public static ISessionFactory CreateSessionFactory() 
{ 
    var config = Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2008 
      .ConnectionString(c => c.FromConnectionStringWithKey("myConnection"))) 
      .Mappings(m => m.FluentMappings.Add<FeaturesMap>()) 
      .ExposeConfiguration(p => p.SetProperty("current_session_context_class", "web")) 
      .BuildConfiguration(); 

      return config.BuildSessionFactory();    
} 

Global.asax

public class MvcApplication : System.Web.HttpApplication 
{ 
    //SessionPerWebRequest is ommited here as well as other content 
    public static ISessionFactory SessionFactory = 
       SessionProvider.CreateSessionFactory(); 

    protected void Application_Start() 
    { 
     SessionFactory.OpenSession(); 
    } 
} 

İçinde myController ben şu var:

public ActionResult Index() 
{ 
    return View(GetData()); 
} 

private IList<FeaturesViewModel> GetData() 
{ 
    List<Features> data; 
    using (ISession session = MvcApplication.SessionFactory.GetCurrentSession()) 
    { 
      using (ITransaction tx = session.BeginTransaction()) 
      { 
       data = session.Query<Features>().Take(5).ToList(); 
       tx.Commit(); 

       var viewModelData = FeaturesViewModel.FromDomainModel(data); 
       return viewModelData; 
      } 
     } 
} 
+1

Başlangıç ​​zamanı gerçekten bu kadar önemli mi? Uygun bir dağıtımda bu maliyet sıklıkla oluşmamalıdır. Web uygulamalarıyla ilgili – Lucero

+0

. Bu lightwave öğesinin kullanıldığı bu başlangıç ​​zamanının "bir şey" olduğunu düşünüyorum. Dağıtımını kontrol ettiğimi mi söylüyorsun? – BobRock

+0

Diyorum ki, eğer bu durum her gün veya her birkaç günde bir dağıtılmış ortamda gerçekleşirse (uygulama havuzunuz geri dönüştürüldüğünde), bu maliyetin bir anlaşma olmadığıdır. – Lucero

cevap

19

Yapılandırmaları önbelleğe alarak başlangıç ​​süresini (hem web hem de windows uygulamalarının) geliştirebilirsiniz. Aşağıdaki sınıfı bu işi yapacak:,

private Configuration readConfigFromCacheFileOrBuildIt() 
{ 
    Configuration nhConfigurationCache; 
    var nhCfgCache = new ConfigurationFileCache(MappingsAssembly); 
    var cachedCfg = nhCfgCache.LoadConfigurationFromFile(); 
    if (cachedCfg == null) 
    { 
     nhConfigurationCache = buildConfiguration(); 
     nhCfgCache.SaveConfigurationToFile(nhConfigurationCache); 
    } 
    else 
    { 
     nhConfigurationCache = cachedCfg; 
    } 
    return nhConfigurationCache; 
} 

Sonra BuildSessionFactory çağırmadan önce, biz önbellekten yapılandırma dosyası okuyabilir

using System.IO; 
using System.Reflection; 
using System.Runtime.Serialization.Formatters.Binary; 
using System.Web; 
using NHibernate.Cfg; 

namespace NH32AutoMap.Core 
{ 
    public class ConfigurationFileCache 
    { 
     private readonly string _cacheFile; 
     private readonly Assembly _definitionsAssembly; 

     public ConfigurationFileCache(Assembly definitionsAssembly) 
     { 
      _definitionsAssembly = definitionsAssembly; 
      _cacheFile = "nh.cfg"; 
      if (HttpContext.Current != null) //for the web apps 
       _cacheFile = HttpContext.Current.Server.MapPath(
           string.Format("~/App_Data/{0}", _cacheFile) 
           ); 
     } 

     public void DeleteCacheFile() 
     { 
      if (File.Exists(_cacheFile)) 
       File.Delete(_cacheFile); 
     } 

     public bool IsConfigurationFileValid 
     { 
      get 
      { 
       if (!File.Exists(_cacheFile)) 
        return false; 
       var configInfo = new FileInfo(_cacheFile); 
       var asmInfo = new FileInfo(_definitionsAssembly.Location); 

       if (configInfo.Length < 5 * 1024) 
        return false; 

       return configInfo.LastWriteTime >= asmInfo.LastWriteTime; 
      } 
     } 

     public void SaveConfigurationToFile(Configuration configuration) 
     { 
      using (var file = File.Open(_cacheFile, FileMode.Create)) 
      { 
       var bf = new BinaryFormatter(); 
       bf.Serialize(file, configuration); 
      } 
     } 

     public Configuration LoadConfigurationFromFile() 
     { 
      if (!IsConfigurationFileValid) 
       return null; 

      using (var file = File.Open(_cacheFile, FileMode.Open, FileAccess.Read)) 
      { 
       var bf = new BinaryFormatter(); 
       return bf.Deserialize(file) as Configuration; 
      } 
     } 
    } 
} 

o kullanmak için ya eşleştirmeleri değişip değişmediğini, onu inşa ve yeniden önbelleğe: (^):

public ISessionFactory SetUpSessionFactory() 
{ 
    var config = readConfigFromCacheFileOrBuildIt(); 
    var sessionFactory = config.BuildSessionFactory(); 

Burada tam bir örnek bulabilirsiniz. + Çalıştırmak istiyorsanız, ana uygulamaların derlemesinden ayrı etki alanı sınıfları ve eşleme tanımları derlemeleri (ConfigurationFileCache sınıfı, önbellek dosyasının önbellek dosyasının LastWriteTime öğesinden daha yeni olması durumunda önbellek dosyasını siler).

+0

FYI: Bunu 3.3'te denedim ve farketmez. Belki ssd'im eski HD'lerden daha hızlıdır, ancak başlangıç ​​problemi kalır. – Candide

2

IIRC doğru, bu iyi bir fikir değil HttpApplication (veya MvcApplication gibi alt sınıfları) çalışmasında nesne oluşturma . Application_Start işleyicisinde oturum fabrikasını oluşturmak daha iyidir.

NHibernate profiler'i kaldırmalısınız (tüm profilleyiciler ölçümleri etkileyebileceğinden). Bunun yerine, CreateSessionFactory() öğesine çağırın ve doğru bir ölçüm elde etmek için Stopwatch sınıfının kullanımıyla çevreleyin.

Veritabanı sunucunuz yanıt vermekte yavaş mı oluyor? Bağlantı havuzu nedeniyle bu sadece ilk fırsatta fark edilebilir.

NHibernate'i başlatmak için biraz zaman ayırın, ancak hafif bir varlıkla 4 saniye çok fazla görünebilir. Bu elbette test sisteminin genel performansından elbette etkileniyor.

+0

numaralı telefondan, Application_Start yöntemine nasıl benzemesi gerektiğini göstermenizi isteyebilirim. Teşekkürler – BobRock

+0

Özgün kod ile ilgili olarak, sadece CreateSessionFactory() içine Application_Start() ve OpenSession() çağrısı Application_BeginRequest() içine çağırın. Application_EndRequest() içindeki oturumu kapatmak için uygun kodu ekleyin. Başlangıcı Kullanarak EndRequest, istek başına oturum modeline karşılık gelir. –

İlgili konular