【问题标题】:Does Having Hundreds of Readonly Static Variables Cause Performance Issues?拥有数百个只读静态变量会导致性能问题吗?
【发布时间】:2022-08-20 15:35:36
【问题描述】:

我正在开发一个新的Asp.Net MVC project,这次为了更好地控制应用程序的静态内容,我计划将所有内容作为可重用属性存储在readonly static variables 中。这些值在应用程序的整个生命周期中都不会改变。

使用示例:

  • 我创建了一个将所有消息保存在静态变量中的类,因此如果我想更改默认保存消息,我可以从这里更改它,而无需更改项目中的每一次出现。这也包括验证消息。 (数量可能会迅速增长,具体取决于项目的规模)

  • 其他用途:存储所有与应用程序相关的属性,例如版本、标题、密钥等等。我还计划存储按钮文本和其他 UI 控件相关属性,以便可以轻松自定义它们,例如我不知道 CSS 类。

  • 更不用说,除了上述之外,我还有一些静态类,例如带有一些静态方法的 Data Access Helpers 和 Utility Functions。

样本类:

public static class Messages
    {
        public static class Response
        {
            public readonly static string SUCCESS = \"Process completed successfully\";
            public readonly static string FAILED = \"Process failed\";
            public readonly static string ERROR = \"Some error occured\";
            public readonly static string OPRNOTPERFORMED = \"Operation aborted/failed for some unknown reason. Please contact your administrator\";

            //LOGIN
            public readonly static string USERNOTFOUND = \"Invalid username or password\";
            public readonly static string USERINACTIVE = \"User is not active. Please contact your administrator\";
            public readonly static string NOROLEDEFINED = \"User does not have any valid authority to access the application. Please contact your administrator\";
            public readonly static string FORCELOGOUT = \"You have been logged out. Please login again\";

            //MASTERS
            public readonly static string NOSTATESFOUND = \"No states found in database. please contact your administrator\";
            public readonly static string APPCHOICENOTFOUND = \"Option not found in the database. Please contact your system administrator.\";

            //COMPANY
            public readonly static string INVALIDCOMPANY = \"Please sign out from the application and login again before performing further opreations\";
        }
        public static class Description
        {
            //COMPANY
            public readonly static string INVALIDCOMPANY = \"Company value changed between 2 consiquent requests. This happens when you left the page idle for so long. Please login again before performing further operations.\";
        }
        public static class Instructions
        {
            public readonly static string MANDATORY_FIELDS = \"Fields marked with <i class=\'text-warning-dark fw-bold fs-6\'>*</i> cannot be blank.\";
        }
    }

到目前为止,这些都只是纸上谈兵。我愿意采用这种方法,以便我可以根据不同客户的需求轻松自定义文本内容。但在那之前,我有几个疑问要澄清。

  • 在我们运行 Web 应用程序时,是否所有静态变量都已初始化并存储在内存中?
  • 是否所有静态变量在 Web 应用程序的整个生命周期中都保留在内存中,无论其在当前视图中的使用情况如何?
  • 在将源代码转换为字节码时,编译器是否将出现的静态变量替换为其实际值? (当我反编译类文件时,我在java中看到了这一点,无论我在哪里使用静态变量,它都会被它的实际值替换)。

另一个例子:

public class Select
    {
        private static readonly SelectListItem defaultChoice = new SelectListItem { Text = \"Select\", Value = \"\" };
        public static readonly IEnumerable<SelectListItem> ISACTIVE = new List<SelectListItem>
        {
            new SelectListItem {Text = \"Active\", Value = \"true\"},
            new SelectListItem {Text = \"Inactive\", Value = \"false\"}
        };
        private static IList<SelectListItem> STATES;

        public static IEnumerable<SelectListItem> GetStates(string sessionHash)
        {
            if (sessionHash == null)
            {
                return null;
            }
            if (STATES == null)
            {
                StateService stateService = new StateService(sessionHash);
                ProcessResponse response = stateService.GetStates();
                IList<StateModel> statesModel = (IList<StateModel>)response.Data[0];
                STATES = new List<SelectListItem>();
                STATES.Add(defaultChoice);
                foreach (StateModel state in statesModel)
                {
                    STATES.Add(new SelectListItem { Text = state.Name, Value = state.StateId.ToString() });
                }
            }
            return STATES;
        }

        public static IEnumerable<SelectListItem> AppChoices(IList<AppChoicesModel> choicesModel)
        {
            IList<SelectListItem> choices = new List<SelectListItem>();
            choices.Add(defaultChoice);
            if (choicesModel != null && choicesModel.Count > 0)
            {
                foreach(AppChoicesModel choice in choicesModel)
                {
                    choices.Add(new SelectListItem { Text = choice.Text, Value = choice.Value });
                }
            }
            return choices;
        }
    }

视图中的用法

@model Cygnus.View.Models.Company.CompanyBranch
@using Cygnus.Data.Constants

@{
    Layout = \"~/Views/Shared/_LayoutDashboard.cshtml\";
    ViewBag.Title = Titles.Company.BRANCHT;
    ViewBag.SubTitle = Titles.Company.BRANCHST;
    var moduleName = Routes.Company.BRANCH;
    var isActive = Select.ISACTIVE;
    var states = Select.GetStates(Session[Codes.SessionParams.HASH].ToString());
    Html.RenderPartial(Routes.Commons.PROCRESPONSE);
}

<div class=\"container-fluid\">
    <div class=\"row\">
        <!-- left column -->
        <div id=\"@string.Format(\"{0}Form_Container\", @moduleName)\" class=\"col-md-7 mt-1 collapse show\">
            <!-- general form elements -->
            <div class=\"card card-info\">
                <div class=\"card-header\">
                    <h3 class=\"card-title\">@ViewBag.SubTitle</h3>
                </div>
                <!-- /.card-header -->
                <!-- form start -->
                @using (Html.BeginForm(moduleName, Routes.Company.CONTROLLER, FormMethod.Post, new { @name = moduleName }))
                {
                    @Html.HiddenFor(model => model.CompanyId)
                    @Html.HiddenFor(model => model.CompanyBranchId)
                    @Html.AntiForgeryToken()
                <div class=\"card-body\">
                    <div class=\"row gx-3\">
                        <div class=\"col-10\">
                            <i class=\"fas fa-info-circle text-info mr-2\"></i>@Html.Raw(@Messages.Instructions.MANDATORY_FIELDS)
                        </div>
                        <div class=\"col-2\">
                            <button class=\"btn btn-block btn-info btn-flat size-width-auto float-right\" value=\"@Codes.ButtonValue.ADD\" name=\"@Codes.ButtonGroupName.ACTION\" ><i class=\"fas fa-plus-square fa-1xl align-middle mr-2\"></i><span class=\"align-middle\">@Codes.ButtonValue.NEW</span></button>
                        </div>
                    </div>
                    <div class=\"row gx-3 mt-3\">
                        <div class=\"input-group-sm col\">
                            <label for=\"Name\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.Name)</label>
                            @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = \"form-control input-required\", @placeholder = \"Branch Name\" } })
                            @Html.ValidationMessageFor(model => model.Name, \"\", new { @class = \"text-danger fs-6-5\" })
                        </div>
                        <div class=\"input-group-sm col-4\">
                            <label for=\"Code\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.Code)</label>
                            @Html.EditorFor(model => model.Code, new { htmlAttributes = new { @class = \"form-control input-required\", @placeholder = \"Branch Code\" } })
                            @Html.ValidationMessageFor(model => model.Code, \"\", new { @class = \"text-danger fs-6-5\" })
                        </div>
                    </div>
                    <div class=\"row gx-3 mt-5px\">
                    <div class=\"input-group-sm col\">
                        <label for=\"State\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.State)</label>
                        @Html.DropDownListFor(model => model.State, states, new { @class = \"form-control input-required\" })
                        @Html.ValidationMessageFor(model => model.State, \"\", new { @class = \"text-danger fs-6-5\" })
                    </div>
                    <div class=\"input-group-sm col-2\">
                        <label for=\"Pincode\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.Pincode)</label>
                        @Html.EditorFor(model => model.Pincode, new { htmlAttributes = new { @class = \"form-control input-required\", @placeholder = \"Pincode\" } })
                        @Html.ValidationMessageFor(model => model.Pincode, \"\", new { @class = \"text-danger fs-6-5\" })
                    </div>
                    <div class=\"input-group-sm col\">
                        <label for=\"BranchType\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.BranchType)</label>
                        @Html.DropDownListFor(model => model.BranchType, Model.BranchTypeList, new { @class = \"form-control input-required\" })
                        @Html.ValidationMessageFor(model => model.BranchType, \"\", new { @class = \"text-danger fs-6-5\" })
                    </div>
                </div>
                    <div class=\"row gx-3 mt-5px\">
                        <div class=\"input-group-sm col\">
                            <label for=\"IsActive\" class=\"fw-semibold\">@Html.DisplayNameFor(model => model.IsActive)</label>
                            @Html.DropDownListFor(model => model.IsActive, isActive, new { @class = \"form-control\" })
                            @Html.ValidationMessageFor(model => model.IsActive, \"\", new { @class = \"text-danger fs-6-5\" })
                        </div>
                    </div>
                </div>
                    <!-- /.card-body -->
                    <div class=\"card-footer\">
                        <button type=\"submit\" value=\"@Codes.ButtonValue.SAVE\" name=\"@Codes.ButtonGroupName.ACTION\" class=\"btn btn-success px-5\">@Codes.ButtonValue.SAVE</button>
                        <div>@Html.ValidationSummary(true, \"\", new { @class = \"text-danger\" })</div>
                    </div>
                }
            </div>
            <!-- /.card -->
        </div>
        <div class=\"col-md mt-1\">
            @{
                Html.RenderAction(Routes.Company.BRANCHLIST, Routes.Company.CONTROLLER);
            }
        </div>
    </div>
</div>
@section Scripts {
    @Scripts.Render(\"~/Scripts/Cygnus/Company.js\")
    <script>
        $(function () {
            var tableId = \"#listOfCompanyBranch\";
            initDataTableWithDefaultToolbar(tableId, \'@moduleName\');
            attachRowDataEvenOnATag(tableId);
        });
        function onRowClicked(rowData, row) {
            let formElement = $(\"#@string.Format(\"{0}Form_Container\",moduleName)\");
            if ($(formElement).is(\'.collapse:not(.show)\'))
                $(formElement).collapse(\"show\");
            document.getElementById(\"CompanyBranchId\").value = $(row).attr(\"data-branch\");
            document.getElementById(\"CompanyId\").value = $(row).attr(\"data-company\");
            FillFormControls(formArr[\"@moduleName\"], rowData);
            $(\"#IsActive\").val((rowData[13]).toLocaleLowerCase());
        }
    </script>
}

    标签: asp.net asp.net-mvc web-applications static-variables readonly-variable


    【解决方案1】:

    拥有数百个只读静态变量是否会导致性能下降 问题?

    不,您示例中的变量每个都是几个字节。假设您有 500 个变量,每个变量有 20 个字节。那将是10KB。现代 Web 服务器通常具有数 GB 的内存,因此您不太可能遇到任何性能问题,因为您正在缓存 10KB 的数据。有关static variables 的更多信息,请参见此处。


    IMO,具有太多静态类型(类/变量)的主要问题是您不知道在哪里可以找到它们。在您提供的示例中,您似乎将一些常量硬编码到静态变量中。 IMO 很好,只要:

    1. 您没有将配置变量定义为常量(连接字符串之类的东西,取决于环境)
    2. 您正在使用逻辑方法对这些常量进行分组,因此很容易找到它们
    3. 我会尝试限制这些常量的大小(不是因为性能,而是为了保持代码干净)

      查看您的代码,可能有更优雅的方式来实现这一点,例如您可以定义一个名为IResponse 的接口:

      interface IResponce
      {
         short Code { get; }
      
         string CssColor { get; }
      
         string Message { get; }
      }
      

      并为响应类型定义不同的类,例如:

      public class SuccessResponse : IResponse
      {
         public short Code => 0;
      
         public string CssColor => "green";
      
         public string Message => "Process completed successfully";
      }
      
      public class FailureResponse : IResponse
      {
         public short Code => 1;
      
         string CssColor => "red";
      
         public string Message => "Process failed";
      }
      

    【讨论】:

    • 感谢您的建议以及您分享的有关静态变量的链接。谢啦!!
    猜你喜欢
    • 2018-08-11
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    相关资源
    最近更新 更多