2012-05-26 13 views
18

मैंने परीक्षण ऐप लागू किया है। जो एमएसएसक्ल डीबी के अंदर डीबी ऑब्जेक्ट में धाराप्रवाह निबर्ननेट मैपिंग का उपयोग करता है। चूंकि मैं ठीक ट्यून निब सीखना चाहता हूं। mvc3 अनुप्रयोग, मैं इस ऐप का उपयोग कर रहा हूँ। परीक्षण उद्देश्यों के लिए जिनके पास 10 enum गुणों और एक स्ट्रिंग संपत्ति के साथ केवल एक साधारण इकाई है। तो, यह वास्तव में लाइटवॉव है, फिर भी निबर्ननेट प्रोफाइलर के अनुसार स्टार्टअप समय 4.37 सेकेंड है। जो एक इकाई को कुछ लाइनों की जांच/अनचेक संपत्ति के साथ प्रस्तुत करने में वास्तव में धीमी है।निबर्ननेट सत्र कारखाने को अनुकूलित करना, वेब ऐप का स्टार्टअप समय वास्तव में धीमा

कोड निम्न है। 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(); 
    } 
} 

अंदर myController मैं निम्नलिखित है:

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

क्या स्टार्टअप समय वास्तव में महत्वपूर्ण है? उचित तैनाती में यह लागत अक्सर नहीं होनी चाहिए। वेब ऐप्स के संबंध में – Lucero

+0

। मुझे लगता है कि इस लाइटवॉव इकाई का उपयोग करके यह स्टार्टअप समय "कुछ" है। आप कह रहे हैं कि मैं तैनाती की जांच करता हूं? – BobRock

+0

मैं जो कह रहा हूं वह यह है कि यदि यह हर दिन या तैनात वातावरण में हर दिन एक बार होता है (जब भी आपका एप्लिकेशन पूल रीसाइक्लिंग हो जाता है), वह लागत एक डीलरब्रेकर नहीं है। – Lucero

उत्तर

19

आप कॉन्फ़िगरेशन को कैश करके स्टार्टअप समय (वेब ​​और विंडोज अनुप्रयोगों दोनों में) को बेहतर बना सकते हैं। निम्नलिखित वर्ग यह काम कर देगा:

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; 
} 

और फिर BuildSessionFactory कॉल करने से पहले, हम कैश से कॉन्फ़िग फ़ाइल पढ़ सकते हैं

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; 
      } 
     } 
    } 
} 

कि उपयोग करने के लिए, या यदि मैपिंग बदल दिया है, इसे बनाने और इसे फिर से कैश: (^):

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

यहाँ आप एक पूर्ण नमूना पा सकते हैं। + यदि आप इसे काम करना चाहते हैं, तो मुख्य अनुप्रयोग की असेंबली से अलग डोमेन वर्ग और मैपिंग परिभाषा असेंबली (क्योंकि कॉन्फ़िगरेशनफाइल कैश क्लास कैश फ़ाइल को हटा देगी यदि मैपिंग परिभाषा असेंबली कैश फ़ाइल के LastWriteTime से नई है)।

+0

एफवाईआई: मैंने 3.3 पर यह कोशिश की है और इससे कोई फर्क नहीं पड़ता। शायद मेरा एसएसडी पुराने एचडी से तेज है, लेकिन स्टार्टअप समस्या बनी हुई है। – Candide

2

IIRC सही ढंग से, यह करने के लिए एक अच्छा विचार नहीं है HttpAplication (या इसके उपखंड जैसे एमवीसी अनुप्रयोग) के निर्माता में ऑब्जेक्ट्स बनाएं । Application_Start हैंडलर में सत्र फ़ैक्टरी बनाने के लिए बेहतर।

आपको NHibernate प्रोफाइलर को हटा देना चाहिए (क्योंकि सभी प्रोफाइलर माप को प्रभावित कर सकते हैं)। इसके बजाए, CreateSessionFactory() पर कॉल करें और सटीक माप प्राप्त करने के लिए स्टॉपवॉच क्लास के उपयोग से घिराएं।

क्या आपका डेटाबेस सर्वर प्रतिक्रिया देने में धीमा है? कनेक्शन पूलिंग के कारण यह केवल पहले अवसर पर ध्यान देने योग्य हो सकता है।

एनएचबेर्नेट को प्रारंभ करने में कुछ समय लगता है, लेकिन एक हल्के इकाई के साथ 4 सेकंड बहुत अधिक प्रतीत होते हैं। यह निश्चित रूप से परीक्षण प्रणाली के सामान्य प्रदर्शन से प्रभावित है।

+0

इस कोड को ऊपर दिमाग में रखते हुए मैं आपको यह दिखाने के लिए कह सकता हूं कि एप्लिकेशन_स्टार्ट विधि की तरह कैसा दिखना चाहिए। धन्यवाद – BobRock

+0

आपके मूल कोड के संबंध में, केवल Create_essionFactory() को एप्लिकेशन_स्टार्ट() में कॉल करें और Open_Bession() को Application_BeginRequest() में कॉल करें। Application_EndRequest() में सत्र को बंद करने के लिए उपयुक्त कोड जोड़ें। प्रारंभ का उपयोग करना | EndRequest सत्र-प्रति-अनुरोध पैटर्न से मेल खाता है। –