วิธีหลีกเลี่ยงการโหลดชุดประกอบที่ไม่จำเป็น

แอปพลิเคชัน ASP.NET .NET 4.6 MVC4 โหลดแอสเซมบลีที่ไม่จำเป็น เช่น System.Data.OracleClient ออราเคิลไม่ได้ใช้

การพึ่งพาแอสเซมบลีถูกสร้างขึ้นโดยใช้โค้ดในคอนโทรลเลอร์

        var sb = new StringBuilder();
        foreach (Assembly b in AppDomain.CurrentDomain.GetAssemblies())
        {
            sb.AppendLine(b.FullName);
            foreach (AssemblyName an in b.GetReferencedAssemblies())
                sb.AppendLine("   " + an.Name);
        }

เอาท์พุทอยู่ด้านล่าง ตามการอ้างอิง System.Web นี้ไปยัง System.Design และ System.Design การอ้างอิงถึง System.Data.OracleClient

แอปพลิเคชัน MVC ทำงานในเซิร์ฟเวอร์ VPS ที่มีหน่วยความจำจำกัด จะแก้ไขปัญหานี้อย่างไรไม่ให้โหลดแอสเซมบลีที่ไม่จำเป็น? หวังว่านี่จะช่วยทำให้หน่วยความจำบางส่วนว่างในเซิร์ฟเวอร์ VPS

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
   mscorlib
   System.Drawing
   System
   System.Configuration
   System.Core
   System.Data
   System.Xml
   System.DirectoryServices
   System.EnterpriseServices
   System.Web.RegularExpressions
   System.Design
   System.Web.ApplicationServices
   System.ComponentModel.DataAnnotations
   System.DirectoryServices.Protocols
   System.Security
   System.Runtime.Caching
   System.ServiceProcess
   System.Web.Services
   Microsoft.Build.Utilities.v4.0
   Microsoft.Build.Framework
   Microsoft.Build.Tasks.v4.0
   System.Windows.Forms
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   mscorlib
   System.Configuration
   System.Xml
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   mscorlib
   System
   System.Xml
   System.Numerics
   System.Security
System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
   mscorlib
   System
   System.Configuration
System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
   mscorlib
   System
   System.Xml
   System.Security
   System.Core
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   mscorlib
   System
   System.Data.SqlXml
   System.Configuration
System.Runtime.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
   mscorlib
   System
   System.Data
   System.Configuration
Microsoft.Build.Utilities.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
   mscorlib
   Microsoft.Build.Framework
   System
   System.Xml
   System.Core
...
System.Data.OracleClient, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
   mscorlib
   System.Configuration
   System.Data
   System.Transactions
   System
   System.EnterpriseServices

ส่วนการเชื่อมโยง web.config ไม่มีอยู่ด้วย:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

อัปเดต

ฉันลองตามคำตอบเพื่อวางคำสั่งลบไปที่ web.config แต่มีข้อผิดพลาด

ป้อนคำอธิบายรูปภาพที่นี่

พยายามลบส่วน oracle ตามคำตอบโดยใช้

<configuration>
  <configSections>
    <section name="system.data.oracleclient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <remove name="system.data.oracleclient"></remove>
    </section>
  </configSections>
  ...

แต่มีข้อผิดพลาด:

ป้อนคำอธิบายรูปภาพที่นี่

จะแก้ไขได้อย่างไร?


person Andrus    schedule 17.10.2016    source แหล่งที่มา
comment
คลิกขวาที่ข้อมูลอ้างอิงในโครงการแล้วคลิกลบจะทำอย่างนั้น คุณกำลังมองหาตัวเลือกอื่นหรือไม่?   -  person Shiham    schedule 17.10.2016
comment
System.Data.OracleClient ไม่ได้ถูกอ้างอิงโดยโปรเจ็กต์ใด ๆ ที่เป็นโซลูชัน อย่างไรก็ตาม เอาต์พุตที่เป็นปัญหาแสดงว่ากำลังโหลดอยู่   -  person Andrus    schedule 17.10.2016
comment
มีการอ้างอิงในส่วนการรวมแอสเซมบลีรันไทม์บนเว็บการกำหนดค่าหรือไม่   -  person Shiham    schedule 17.10.2016
comment
ไม่ ฉันอัปเดตคำถามและเพิ่มส่วนการผูกมัด ฉันค้นหาวิธีแก้ปัญหาสำหรับคำ oracle และไม่พบข้อความที่ใช้หรือการอ้างอิงโดยตรง   -  person Andrus    schedule 17.10.2016
comment
ฉันต้องการทบทวนหัวข้อนี้ด้วยตัวเอง และพบลิงก์ที่มีประโยชน์มาก: weblog.west-wind.com/posts/2012/Nov/03/ จากบทความ ดูเหมือนว่าคุณจะโชคไม่ดี: ASP.NET จะโหลดการอ้างอิงทั้งหมดล่วงหน้า (แม้จะไม่ได้ใช้ก็ตาม) ในขณะที่เช่น แอปคอนโซลแบบธรรมดาจะไม่เป็นเช่นนั้น ถ้าทั้งหมดนี้เป็นจริง คุณก็อาจจะต้องอยู่กับมัน   -  person Peter B    schedule 17.10.2016
comment
ASP.NET ไม่มีการอ้างอิงผู้ให้บริการข้อมูลแบบฮาร์ดโค้ด System.Data.OracleClient ไม่ควรอ้างอิงจาก System.Web, System.Design และแอสเซมบลีที่คล้ายกัน ทำไมยังโหลดอยู่? อาจมีการกำหนดค่าที่ซ่อนอยู่ซึ่งบังคับให้โหลดแบบไดนามิกหรือไม่   -  person Andrus    schedule 17.10.2016
comment
ตรวจสอบอินสแตนซ์ของ Oracle ใน machine.config ของคุณ   -  person hometoast    schedule 17.10.2016


คำตอบ (2)


มีแอสเซมบลีอยู่สามประเภทบนเว็บแอปพลิเคชัน

  1. แอสเซมบลีที่มาพร้อมกับไลบรารี (dll) ที่คุณใช้
  2. แอสเซมบลีที่เป็นเวอร์ชันที่คอมไพล์ของเว็บแอปพลิเคชันของคุณ
  3. แอสเซมบลีที่เป็นหลักในการรันไซต์

ห้องสมุด

ในกรณีแรก คุณสามารถเพิ่มประสิทธิภาพ ไลบรารีของคุณ โดยลบการอ้างอิงที่ไม่จำเป็นโดยตรงบนโปรเจ็กต์ dll ของคุณ

อ้างอิง

ในกรณีที่สองเพื่อเพิ่มประสิทธิภาพหน้าเว็บของคุณและสิ่งที่จะคอมไพล์ คุณต้องลบการอ้างอิงที่ไม่จำเป็นในโค้ดที่อยู่ด้านหลัง... เช่น หน้ามักจะมีบรรทัดแรกนี้

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

และที่ไม่ได้ใช้ก็มีสีเทาก็เอาออกได้...

แอสเซมบลีของเว็บ

และตอนนี้ส่วนที่ยาก - ยากเพราะคุณต้องเล่นเกม "ลอง/ล้มเหลว" ตอนนี้คุณสามารถลบอะไรได้บ้างและจากที่ไหน

ก่อนอื่นฉันจะค้นหาอะไรที่จะลบ... และคำตอบอยู่ที่ global web.config บน asp.net ในกรณีของฉัน ฉันจะไปที่ไดเร็กทอรี windows บนเวอร์ชันเฟรมเวิร์กปัจจุบันของฉัน บนไดเร็กทอรี config และค้นหา web.config

ที่นั่นฉันพบกุญแจบางดอก....

ขั้นแรก คุณสามารถลบ โมดูล Http ที่ไม่จำเป็นเพื่อให้ไปป์ไลน์เร็วขึ้น ใน httpModulesession บน web.config

นี่คือสิ่งที่ฉันเห็นใน global web.config

<httpModules>
    <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
    <add name="Session" type="System.Web.SessionState.SessionStateModule" />
    <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
    <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
    <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
    <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
    <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
    <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
    <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" />
    <add name="Profile" type="System.Web.Profile.ProfileModule" />
    <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
    <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>

และฉันไปที่ web.config บนแอปพลิเคชันของฉัน และนี่คือวิธีที่ฉันจะลบสิ่งที่ฉันไม่ได้ใช้:

<httpModules>
  <remove name="Session" />
  <remove name="PassportAuthentication" />
  <remove name="AnonymousIdentification" />
</httpModules>

สำหรับกรณีของคุณ ฉันจะดำเนินการต่อในเซสชันแอสเซมบลี นี่คือสิ่งที่ฉันเห็นใน global web.config:

<compilation>
        <assemblies>
            <remove assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="mscorlib" />
            <add assembly="Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.WorkflowServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Web.DynamicData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="*" />
            <add assembly="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </assemblies>

เนื่องจากฉันคัดลอก/วางไปที่ web.config ของฉันและวาง <clear /> ในบรรทัดแรก จากนั้นฉันเริ่มลบบรรทัดที่ฉันรู้ว่าโปรแกรมของฉันไม่ได้ใช้... และระวังที่จะเก็บบรรทัดนี้ <add assembly="*" /> และในตอนท้าย สิ่งนี้บอกว่าจะเพิ่มไลบรารีของคุณจากไดเรกทอรี dll ของคุณ

            <assemblies>
                <clear />
                <add assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
                <add assembly="mscorlib" />
                <add assembly="Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
....
                <add assembly="*" />
            </assemblies>

การทำสิ่งนี้และการลบอันที่คุณไม่ได้ใช้ออก โดยการลบและดูว่าแอปพลิเคชันของคุณยังทำงานอยู่หรือไม่ คุณสามารถจำกัดแอสเซมบลีที่คุณใช้ได้มาก

ฉันทำการทดสอบง่ายๆ และลบบรรทัดนี้ออก

<add assembly="System.WorkflowServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

ฉันนับจาก 83 เหลือ 79 เฉพาะแอสเซมบลีที่โหลดในครั้งนี้ ทำไมมากกว่าหนึ่งลบ? เพราะ WorkflowServices โหลดเพิ่มด้วยตัวเอง

หากต้องการลบบางสิ่งออกจากส่วนการกำหนดค่า อีกครั้งบน web.config ของคุณ คุณดำเนินการดังนี้:

<configuration> 
  <configSections>
        <remove name="system.data.oracleclient"></remove>
...
person Aristos    schedule 17.10.2016
comment
OracleClient ไม่ได้อยู่ในตำแหน่งที่อธิบายไว้ในคำตอบ ค่าเริ่มต้น machine.config ประกอบด้วย <section name="system.data.oracleclient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> สิ่งนี้อาจทำให้ไคลเอนต์ Oracle โหลดได้หรือไม่ จะบังคับให้. NET ไม่โหลดโดยไม่ต้องเปลี่ยน machine.config ด้วยตนเองในทุกเซิร์ฟเวอร์ของลูกค้าได้อย่างไร - person Andrus; 17.10.2016
comment
@Andrus คล้ายกันใน configSection บน web.config ของคุณเพิ่มบรรทัด <configSections><remove name="system.data.oracleclient"></remove>... เพื่อลบออก - person Aristos; 17.10.2016
comment
ซึ่งทำให้เกิดข้อผิดพลาด invalid child element 'remove' ฉันอัปเดตคำถามโดยพยายามลบออก - person Andrus; 17.10.2016
comment
Oracle config ไม่ได้ถูกกำหนดไว้ที่ใดเลย การมีอยู่ของคำจำกัดความส่วนของ Oracle ในไฟล์ machine.config จะทำให้ System.Data.OracleClient โหลดแอสเซมบลีหรือไม่ - person Andrus; 17.10.2016
comment
@Andrus สิ่งที่ฉันพิมพ์ที่นี่ฉันทดสอบครั้งแรกในคอมพิวเตอร์ของฉันด้วยเหตุผลบางอย่างไม่ใช่ข้อผิดพลาด แต่มันใช้งานได้ ตอนนี้คำจำกัดความส่วนของ oracle ไม่ทำให้เกิดการโหลดแอสเซมบลีใด ๆ เว้นแต่คุณจะใช้บน web.config ส่วนนี้ - person Aristos; 17.10.2016
comment
ฉันโพสต์ไว้ใน stackoverflow.com/questions/40094420/ - person Andrus; 17.10.2016

เวิร์กสเตชันของฉันในที่ทำงานมีการอ้างอิงถึง Oracle ตลอดทั้ง machine.config ของฉัน ฉันเชื่อว่าคุณจะพบการอ้างอิงอันธพาลของคุณที่นั่น

c:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config

person hometoast    schedule 17.10.2016
comment
ค่าเริ่มต้น machine.config มีเพียง <section name="system.data.oracleclient" type="System.Data.Common.DbProviderConfigurationHandler, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> ส่วนการกำหนดค่าไคลเอนต์ Oracle ไม่ได้ถูกกำหนดไว้ที่ใดเลย สิ่งนี้อาจทำให้ไคลเอนต์ Oracle โหลดได้หรือไม่ จะบังคับให้. NET ไม่โหลดโดยไม่ต้องเปลี่ยน machine.config ด้วยตนเองในทุกเซิร์ฟเวอร์ของลูกค้าได้อย่างไร - person Andrus; 17.10.2016