- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
如果我只是浏览应用程序上的一些页面,它大约有 500MB。这些页面中的许多页面都访问数据库,但此时,我只有大约几行,每个 10 个表,主要存储字符串和一些小于 50KB 的小图标。
真正的问题发生在我下载文件时。该文件大约为 140MB,并以 varbinary(MAX)
的形式存储在数据库中。内存使用量在一瞬间突然上升到 1.3GB,然后又回落到 1GB。该操作的代码在这里:
public ActionResult DownloadIpa(int buildId)
{
var build = _unitOfWork.Repository<Build>().GetById(buildId);
var buildFiles = _unitOfWork.Repository<BuildFiles>().GetById(buildId);
if (buildFiles == null)
{
throw new HttpException(404, "Item not found");
}
var app = _unitOfWork.Repository<App>().GetById(build.AppId);
var fileName = app.Name + ".ipa";
app.Downloads++;
_unitOfWork.Repository<App>().Update(app);
_unitOfWork.Save();
return DownloadFile(buildFiles.Ipa, fileName);
}
private ActionResult DownloadFile(byte[] file, string fileName, string type = "application/octet-stream")
{
if (file == null)
{
throw new HttpException(500, "Empty file");
}
if (fileName.Equals(""))
{
throw new HttpException(500, "No name");
}
return File(file, type, fileName);
}
在我的本地计算机上,如果我什么都不做,内存使用量将保持在 1GB。如果我然后返回并导航到某些页面,它会回落到 500MB。
在部署服务器上,无论我做什么,第一次下载后它都保持在 1.6GB。我可以通过不断下载文件来强制增加内存使用量,直到达到 3GB,然后又回落到 1.6GB。
在每个 Controller 中,我都重写了 Dispose()
方法:
protected override void Dispose(bool disposing)
{
_unitOfWork.Dispose();
base.Dispose(disposing);
}
这里指的是:
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_context.Dispose();
}
}
_disposed = true;
}
所以我的工作单元应该在每次处置 Controller 时处置。我正在使用 Unity,并且向 Heirarchical Lifetime Manager 注册了工作单元。
以下是 Profiler 的一些屏幕截图:
我认为这可能是问题所在,或者我走错了路。为什么 Find()
会使用 300MB?
编辑:
存储库:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
internal IDbContext Context;
internal IDbSet<TEntity> DbSet;
public Repository(IDbContext context)
{
Context = context;
DbSet = Context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> GetAll()
{
return DbSet.ToList();
}
public virtual TEntity GetById(object id)
{
return DbSet.Find(id);
}
public TEntity GetSingle(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate).SingleOrDefault();
}
public virtual RepositoryQuery<TEntity> Query()
{
return new RepositoryQuery<TEntity>(this);
}
internal IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
List<Expression<Func<TEntity, object>>> includeProperties = null)
{
IQueryable<TEntity> query = DbSet;
if (includeProperties != null)
{
includeProperties.ForEach(i => query.Include(i));
}
if (filter != null)
{
query = query.Where(filter);
}
if (orderBy != null)
{
query = orderBy(query);
}
return query.ToList();
}
public virtual void Insert(TEntity entity)
{
DbSet.Add(entity);
}
public virtual void Update(TEntity entity)
{
DbSet.Attach(entity);
Context.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(object id)
{
var entity = DbSet.Find(id);
Delete(entity);
}
public virtual void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
DbSet.Attach(entity);
}
DbSet.Remove(entity);
}
}
编辑 2:
我为各种场景运行 dotMemory,这就是我得到的。
红色圆圈表示有时一页访问会发生多次上升和下降。蓝色圆圈表示下载 40MB 文件。绿色圆圈表示下载 140MB 文件。此外,很多时候,即使页面立即加载,内存使用量也会持续增加几秒钟。
最佳答案
因为文件很大,所以它被分配在大对象堆上,该堆是使用 gen2 集合收集的(您在配置文件中看到,紫色 block 是大对象堆,您会在 10 秒后看到它被收集)。
在您的生产服务器上,您很可能拥有比本地机器更多的内存。因为内存压力较小,收集不会那么频繁,这就解释了为什么它会增加一个更高的数字 - LOH 在收集之前有几个文件。
如果在 MVC 和 EF 中的不同缓冲区中,一些数据也被复制到不安全的 block 中,我一点也不会感到惊讶,这解释了非托管内存增长(EF 的细尖峰,MVC 的宽平台)
最后,一个 500MB 的基线对于一个大型项目来说并不完全令人惊讶(疯狂!但确实如此!)
因此,对于您的问题,为什么它很可能会使用这么多内存的答案是“因为它可以”,或者换句话说,因为执行 gen2 收集没有内存压力,并且下载的文件未使用您的大型对象堆,直到收集驱逐它们,因为您的生产服务器上的内存充足。
这甚至可能不是一个真正的问题:如果内存压力更大,就会有更多的收集,而您会发现内存使用率更低。
至于该怎么做,恐怕你对 Entity Framework 不走运。据我所知,它没有流式 API。顺便说一句,WebAPI 确实允许流式传输响应,但是如果您将整个大对象都放在内存中,这对您没有多大帮助(尽管它可能对一些(由我)未开发的 MVC 部分中的非托管内存有所帮助.
关于c# - MVC ASP.NET 正在使用大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25993290/
我有一个加号/减号按钮,希望用户不能选择超过 20 个但不知道如何让它工作。我尝试使用 min="1"max="5 属性,但它们不起作用。这是我的代码和一个 fiddle 链接。https://jsf
我正在尝试复制顶部底部图,如示例 here但它没有正确渲染(紫色系列有 +ve 和 -ve 值,绿色为负值)留下杂乱的人工制品。我也在努力创建一个玩具示例来复制这个问题,所以我希望尽管我缺乏数据,但有
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 6 年前。 社区去年审查了是
这个问题在这里已经有了答案: Adding two positive integers gives negative answer.Why? (4 个答案) 关闭 5 年前。 我遇到了一个奇怪的问题
有谁知道如何将字符串值类型 -4,5 或 5,4 转换为 double -4.5 或 5.4? 最佳答案 只需使用 Double.parseDouble(Locale, String); 糟糕,我很困
我正在尝试根据 TextBlob 分类插入一个仅包含“正”或“负”字符串的新数据框列:对于我的 df 的第一行,结果是 ( pos , 0.75, 0.2499999999999997)我想要' 正
我对 VBA 非常陌生,无法理解如何在一个循环中完成 2 个任务。我非常感谢您的帮助。 我已经能够根据第 3 列中的数据更改第 2 列中的数值,但我不明白如何将负值的字体更改为红色。 表格的大小每月都
欢迎, 我正在使用 jquery 通过 POST 发送表单。 这就是我获得值(value)的方式。 var mytext = $("#textareaid").val(); var dataStrin
double d = 0; // random decimal value with it's integral part within the range of Int32 and always p
我有这个字符串: var a='abc123#xyz123'; 我想构建 2 个正则表达式替换函数: 1) 用 '*' 替换所有确实有 future '#'的字符(不包括'#') 所以结果应该是这样的
我正在使用 DialogFragment。当用户从 Gmail 平板电脑应用程序的屏幕与下面示例图片中的编辑文本进行交互时,我希望正面和负面按钮保持在键盘上方。 在我的尝试中不起作用,这是我的 Dia
从组装艺术一书中,我复制了这句话: In the two’s complement system, the H.O. bit of a number is a sign bit. If the H.O
是否有更好更优雅的方法来实现下面的简单代码(diffYear、A 和 B 是数字): diffYear = yearA - yearB; if (diffYear == 0) { A = B
我正在设计一种语言,并尝试确定 true 应该是 0x01 还是 0xFF。显然,所有非零值都将转换为 true,但我正在尝试确定确切的内部表示。 每种选择的优点和缺点是什么? 最佳答案 没关系,只要
在我的 dialogfragment 类的 OnCreateDialog 中,我正在这样做: AlertDialog.Builder builder = new AlertDialog.Builder
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda usin
我偶然发现了一个奇怪的 NSDecimalNumber 行为:对于某些值,调用 integerValue、longValue、longLongValue 等,返回意想不到的值(value)。示例: l
这个问题在这里已经有了答案: Resolving ambiguous overload on function pointer and std::function for a lambda using
我有这个正则表达式来测试用户输入是否有效: value.length === 0 || value === '-' || (!isNaN(parseFloat(value)) && /^-?\d+\.
我想用高斯混合模型拟合数据集,数据集包含大约 120k 个样本,每个样本有大约 130 个维度。当我使用 matlab 执行此操作时,我运行脚本(簇号为 1000): gm = fitgmdist(d
我是一名优秀的程序员,十分优秀!