【问题标题】:Memory stacks with no good reason?没有充分理由的内存堆栈?
【发布时间】:2013-11-08 10:03:06
【问题描述】:

您好,我正在构建一个 c# Web 应用程序,它需要对每个页面请求运行大量检查。现在我需要缓存这些产品的产品信息和属性,以便堆积内存(显然)。但是当我重新加载一个包含很多产品的页面时,它会将一些带有这些产品名称的 Sql 请求转换为字符串。我注意到字符串占用了大量内存,但是当我准备好使用这些字符串(在本地创建)时,用于这些字符串的内存会不断增加,直到某个(随机)点下降。然后它又开始堆积起来。

我使用 .NET Memory Profiler 来分析内存使用情况,它指出 System.String 甚至比缓存的产品和属性使用更多。

我已经优化了一些在这种情况下建立大量内存的字符串:

优化前

string selectSql = "";
for(var i = 0; i < products.count;i++)
{
    selectSql += "'"+products[i].Name+"', ";
}

优化后

List<string> listSelect = new List<string>();
for(var i = 0; i < products.count;i++)
{
    listSelect.Add(products[i].Name);
}
string joined = "'" + String.Join("', '", listSelect) + "'";

但据我所知,我没有使用很多会建立那么多内存的情况,我该如何清除这些内存?

我不能使用:

GC.Collect();

或者至少有很多人建议反对这种方法,因为它只会提示垃圾收集,而且在我的情况下它不会清理内存。 我已经检查过了

GC.GetTotalMemory(true);

Collect 语句后也是一样。

我哪里出错了我错过了什么或者我可以做些什么来确保这些字符串不会在我的记忆中很长时间?

提前感谢您的宝贵时间。

在请求更多代码之后,我最终将其用作“查询构建器”,listSelect 是前面提到的列表。

StringBuilder sb = new StringBuilder();
sb.Append("SELECT pr.* FROM products pr");
sb.Append("HAVING pr.Name IN(" + "'" + String.Join("', '", listSelect) + "'" + ") ");
sb.Append("ORDER BY pr.`Prijs` ASC LIMIT 1");
db.Sql = sb.ToString();

但是当我做 db.Sql = sb.ToString(); 这不就占用了与创建字符串一样多的内存吗?还是 StringBuilder 仍在以一种好的方式使用它?

【问题讨论】:

  • 使用StringBuilder 连接你的字符串。另外,你在用̔joined做什么?请发布更多代码。
  • 我们都很难比垃圾收集器更聪明。不要尝试。它在其他计算机上的工作方式会有所不同,或者如果计算机实际使用该空闲内存。正如 ken2k 所说,StringBuilder 虽然很好用。这会导致内存增长较慢,因为它不会为每个连接创建新字符串。
  • 我一直在使用 stringbuilder 进行更大的 sql 查询,但是当我使用 db.Sql = sb.ToString();其中 db 是 mysqldb 而 sb 是 stringbuilder,放在 db.Sql 中的字符串不是也像普通字符串一样占用吗?

标签: c# string memory garbage-collection


【解决方案1】:

您正在观察垃圾收集器的工作。当它需要回收内存时,它会这样做。

除非您遇到性能问题,否则可以使用内存并且您的应用程序运行良好。您无需尝试修复未损坏的内容。

【讨论】:

  • 感谢您的回答,但是当这个应用程序被放置在服务器上(还有几个应用程序)时,它有时会达到 2 GB 的工作集(内存),这会损害其他应用程序的性能,对吧?垃圾收集器是否会立即清除所有不需要的字符串等?因为那样的话,这意味着那些使用的字符串不是在本地使用而是在全球范围内制作并且仍在范围内,对吗?
猜你喜欢
  • 2018-07-24
  • 2011-05-28
  • 1970-01-01
  • 2012-03-07
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
相关资源
最近更新 更多