Session[...] 字典键的字符串文字与常量的性能

发布于 2024-08-28 06:14:54 字数 376 浏览 10 评论 0原文

Session[Constant] 与 Session["String Literal"] 性能

我正在检索用户特定的数据,例如 ViewData["CartItems"] = Session["CartItems"]; ,其中键的字符串文字每一个请求。我应该为此使用常量吗?

如果是,我应该如何实现经常使用的字符串文字,它会显着影响高流量网站的性能吗?


相关问题未解决 ASP.NET MVC 或 会话

Session[Constant] vs Session["String Literal"] Performance

I'm retrieving user-specific data like ViewData["CartItems"] = Session["CartItems"]; with a string literal for keys on every request. Should I be using constants for this?

If yes, how should I go about implementing frequently used string literals and will it significantly affect performance on a high-traffic site?


Related question does not address ASP.NET MVC or Session.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夏夜暖风 2024-09-04 06:14:54

使用常量的原因与可维护性有关,而不是性能。无论哪种方式,性能都大致相同。

对于字符串文字,您永远无法判断它是否与另一个字符串文字相同,是有意还是巧合,因此当需要更改一个字符串文字时,您不知道要更改哪些其他字符串文字。但如果您有常量值,则只需在一处进行更改即可。

坏:

ViewData["username"] = Session["username"];

好:

const UserNameSessionKey = "username";
const UserNameViewDataKey = "username";

ViewData[UserNameViewDataKey] = Session[UserNameSessionkey];

现在想象一下将会话密钥的值更改为“userName”,而不想更改任何 viewdata 键......

The reason to use constants has to do with maintainability, not performance. Performance is about the same either way.

With a string literal, you can never tell whether it's the same as another string literal intentionally or by coincidence, so when it's time to change one, you don't know which other ones to change. But if you have the values in constants, you just make the change in one place.

Bad:

ViewData["username"] = Session["username"];

Good:

const UserNameSessionKey = "username";
const UserNameViewDataKey = "username";

ViewData[UserNameViewDataKey] = Session[UserNameSessionkey];

Now imagine changing the value of the session key to "userName" without wanting to change it for any viewdata key...

请叫√我孤独 2024-09-04 06:14:54

使用常量是因为如果你输入错误,编译器会给你一个错误,而输入错误的字符串只会给你带来奇怪的错误。

性能差异可能非常小,以至于很难测量。

Use the constant because the compiler will give you an error if you mistype it, whereas mistyped strings will just give you wonky bugs.

The performance difference will likely be so small it would be very difficult to measure.

乖乖 2024-09-04 06:14:54

让我们在可维护性方面更进一步。我将引用我关于使用 Session 的其他答案:

假设我们要存储购物车是 ASP.NET MVC 应用程序的 Session。它将存储在 Session["ShoppingCart"] 中,但我们想要简单、强类型的访问和高可测试性:

首先我们定义接口:

public interface ISessionWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

然后我们进行 HttpContext 实现:

public class HttpContextSessionWrapper : ISessionWrapper
{
    private T GetFromSession<T>(string key)
    {
        return (T) HttpContext.Current.Session[key];
    }

    private void SetInSession(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }

    public List<CartItem> ShoppingCart
    {
        get { return GetFromSession<List<CartItem>>("ShoppingCart"); }
        set { SetInSession("ShoppingCart", value); }
    }
}

GetFromSession 和 SetInSession 是使在会话中获取和设置数据更容易。它们可以轻松地重用以访问会话中的其他字段。

然后我们定义我们的基本控制器(适用于 ASP.NET MVC):

public class BaseController : Controller
{
    public ISessionWrapper SessionWrapper { get; set; }

    public BaseController()
    {
        SessionWrapper = new HttpContextSessionWrapper();
    }
}

如果你想在控制器之外使用 Session,你只需创建或注入新的 HttpContextSessionWrapper() 即可。

您可以在控制器测试中将 SessionWrapper 替换为 ISessionWrapper 模拟,因此它不再依赖于 HttpContext。 Session 也更易于使用,因为您调用的是 SessionWrapper.ShoppingCart,而不是调用 (List)Session["ShoppingCart"]。它看起来更好,不是吗?

如果您不使用模型类进行视图,并且我认为使用模型类更好,您可以对 ViewData 执行相同的操作:

public interface IViewDataWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

public class ViewDataWrapper : IViewDataWrapper
{
}

public class BaseController : Controller
{
    public IViewDataWrapper ViewDataWrapper { get; set; }

    public BaseController()
    {
        IViewDataWrapper = new ViewDataWrapper();
    }
}

然后只需在控制器中:

ViewDataWrapper.ShoppingCart = SessionWrapper.ShoppingCart 

或者如果您决定不使用 ViewData 和特定模型:

Model.ShoppingCart = SessionWrapper .ShoppingCart

并且简单地在视图中(如果您为视图定义基类并引入此接口):

<%= ViewDataWrapper.ShoppingCart %>

<%= Model.ShoppingCart %>

没有错误输入的字符串,强类型,美观。

Lets go further with maintainability. I'll quote my other answer about using Session:

Lets say we want to store shopping cart is Session of our ASP.NET MVC application. It will be stored in Session["ShoppingCart"], but we want easy, strongly typed access and high testability:

First we define interface:

public interface ISessionWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

Then we make HttpContext implementation:

public class HttpContextSessionWrapper : ISessionWrapper
{
    private T GetFromSession<T>(string key)
    {
        return (T) HttpContext.Current.Session[key];
    }

    private void SetInSession(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }

    public List<CartItem> ShoppingCart
    {
        get { return GetFromSession<List<CartItem>>("ShoppingCart"); }
        set { SetInSession("ShoppingCart", value); }
    }
}

GetFromSession and SetInSession are helper method that make taking and setting data in Session easier. They can be easily reused to access other fields in Session.

Then we define our base controller (applicable to ASP.NET MVC):

public class BaseController : Controller
{
    public ISessionWrapper SessionWrapper { get; set; }

    public BaseController()
    {
        SessionWrapper = new HttpContextSessionWrapper();
    }
}

If you want to use Session outside controller, you just create or inject new HttpContextSessionWrapper().

You can replace SessionWrapper with ISessionWrapper mock in Controller tests, so it is not dependent on HttpContext anymore. Session is also more easy to use, because instead of calling (List<CartItem>)Session["ShoppingCart"], you call SessionWrapper.ShoppingCart. It looks nicer, isn't it?

If you don't use model class for view and I think using model class is better, you can do the same with ViewData:

public interface IViewDataWrapper
{
    List<CartItem> ShoppingCart { get; set; }
}

public class ViewDataWrapper : IViewDataWrapper
{
}

public class BaseController : Controller
{
    public IViewDataWrapper ViewDataWrapper { get; set; }

    public BaseController()
    {
        IViewDataWrapper = new ViewDataWrapper();
    }
}

And then simply in controller:

ViewDataWrapper.ShoppingCart = SessionWrapper.ShoppingCart 

or if you decide not to use ViewData and specific model:

Model.ShoppingCart = SessionWrapper.ShoppingCart

And simply in view (if you define base class for view and introduce this interface):

<%= ViewDataWrapper.ShoppingCart %>

or

<%= Model.ShoppingCart %>

No mistyped strings, strongly typed, nice looking.

來不及說愛妳 2024-09-04 06:14:54

只是简单说明一下,但许多更好的示例都有一类包含字符串常量的 SessionKeys。这也有助于单元测试,因为您可以在必要时调用单元测试中的常量。

例如(只有一个键,但显然你可以添加更多

public class SessionKeys
{
    public const string UserDto = "UserDto";
}

这样的键(我使用 SessionStateWrapper)

UserDto userDto = _sessionStateWrapper.GetItem(SessionKeys.UserDto) as UserDto;

Just a quick note but a lot of the better examples have a class of SessionKeys containing string constants. This also aids Unit Testing as you can call the constants in your Unit Tests where necessary.

E.g. (just one key but obviously you can add more

public class SessionKeys
{
    public const string UserDto = "UserDto";
}

used as such (I use SessionStateWrapper)

UserDto userDto = _sessionStateWrapper.GetItem(SessionKeys.UserDto) as UserDto;
强辩 2024-09-04 06:14:54

根据关于字典键长度的此基准,较短的键速度更快。此处引用:

C# 中的字典字符串键长度基准

较短的查找键是否明显更快?随着按键变短,查找时间变得更快:

  • 按键 A - 20 个字符:4436 毫秒 [最慢]
  • 按键 B - 10 个字符:2010 毫秒
  • 密钥 C - 5 个字符:1749 毫秒
  • 密钥 D - 2 个字符:1575 毫秒 [最快]

其中:

  • 密钥 A >=“01234567890123456789”;
  • 密钥 B = "0123456789";
  • 键 C = "01234";
  • 键 D = "01";

According to this benchmark on the length of dictionary keys, shorter keys are faster. Quoted here:

Dictionary string key length benchmark in C#

Are shorter lookup keys significantly faster? As keys get shorter, lookup time gets faster:

  • Key A - 20 characters: 4436 ms [slowest]
  • Key B - 10 characters: 2010 ms
  • Key C - 5 characters: 1749 ms
  • Key D - 2 characters: 1575 ms [fastest]

where:

  • Key A = "01234567890123456789";
  • Key B = "0123456789";
  • Key C = "01234";
  • Key D = "01";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文