最近写了一个WinFrom程序。此程序侦听TCP端口,接受消息处理,然后再把处理后的消息,利用线程池通过WebService发送出去(即一进一出)。

在程序编写完成后,进行压力测试。用Fiddler提交1万请求。

                ThreadPool.QueueUserWorkItem((o) =>
{
try
{
APPService.AddLog(o as MDMPortalWCF.LogInfo);//发送此Log时,是提交WebService请求的。
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
} },log);

 使用procexp.exe查看,随着TCP请求的增多,2代GCHeap不断增大。是明显的内存泄漏线索。

使用WinDbg分析,GC2明显大,线程正在忙。发现很多String(LogInfo中的属性)被System.Threading.ThreadPoolWorkQueue.QueueSegment引用。正是内存高的原因。

使用Fiddler查看,发现出乎意料的行为,1万个TCP接受完成后,Log却没有发送完。而是持续之后很久,一直发送,直到几分钟后才发送完成。

    此行为表明,ThreadPool倾向于少数线程排队任务,不倾向于开很多线程迅速完成任务。

当发送日志的任务在ThreadPool的队列排队时,LogInfo不会被GC回收,而是被QueueSegment持有。待ThreadPool执行完成后,QueueSegment不再引用任务对象,故内存被回收。

后来想想,ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)中的state对象,在被执行前,将一直被引用,这是合情合理的。但由于ThreadPool的排队性质,导致内存释放也是缓慢的,往往是人们想不到的。在此记录,以示后人。

2018-03-23  

在网上读到一篇文章(http://www.albahari.com/threading/#_Optimizing_the_Thread_Pool)说的非常详细。更好的解释了如上的现象。SetMinThreads是一种高级优化线程池的技术。线程池策略是经济型的,即尽量节省线程新建,这是为了防止多个短生命期任务造成内存突然膨胀。但当入队的任务,超过半秒执行时间,线程池才开始每半秒新增一个Thread。当然,这也造成了一些问题,比如多个访问互联网的线程,我们希望同时一起访问。这时需要设置ThreadPool.SetMinThreads(100,100),这条语句,告诉线程池管理器,在前100个线程内,不要等待半秒,任务来了,立即创建线程。原文如下:

How Does the Minimum Thread Count Work?

Increasing the thread pool’s minimum thread count to x doesn’t actually force x threads to be created right away — threads are created only on demand. Rather, it instructs the pool manager to create up to x threads the instant they are required. The question, then, is why would the thread pool otherwise delay in creating a thread when it’s needed?

The answer is to prevent a brief burst of short-lived activity from causing a full allocation of threads, suddenly swelling an application’s memory footprint. To illustrate, consider a quad-core computer running a client application that enqueues 40 tasks at once. If each task performs a 10 ms calculation, the whole thing will be over in 100 ms, assuming the work is divided among the four cores. Ideally, we’d want the 40 tasks to run on exactly four threads:

  • Any less and we’d not be making maximum use of all four cores.
  • Any more and we’d be wasting memory and CPU time creating unnecessary threads.

And this is exactly how the thread pool works. Matching the thread count to the core count allows a program to retain a small memory footprint without hurting performance — as long as the threads are efficiently used (which in this case they are).

But now suppose that instead of working for 10 ms, each task queries the Internet, waiting half a second for a response while the local CPU is idle. The pool manager’s thread-economy strategy breaks down; it would now do better to create more threads, so all the Internet queries could happen simultaneously.

Fortunately, the pool manager has a backup plan. If its queue remains stationary for more than half a second, it responds by creating more threads — one every half-second — up to the capacity of the thread pool.

The half-second delay is a two-edged sword. On the one hand, it means that a one-off burst of brief activity doesn’t make a program suddenly consume an extra unnecessary 40 MB (or more) of memory. On the other hand, it can needlessly delay things when a pooled thread blocks, such as when querying a database or calling WebClient.DownloadFile. For this reason, you can tell the pool manager not to delay in the allocation of the first x threads, by calling SetMinThreads, for instance:

ThreadPool.SetMinThreads (50, 50);

(The second value indicates how many threads to assign to I/O completion ports, which are used by the APM, described in Chapter 23 of C# 4.0 in a Nutshell.)

The default value is one thread per core.

.Net线程池ThreadPool导致内存高的问题分析的更多相关文章

  1. 线程池ThreadPool的初探

    一.线程池的适用范围 在日常使用多线程开发的时候,一般都构造一个Thread示例,然后调用Start使之执行.如果一个线程它大部分时间花费在等待某个事件响应的发生然后才予以响应:或者如果在一定期间内重 ...

  2. C#多线程学习 之 线程池[ThreadPool](转)

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  3. 多线程Thread,线程池ThreadPool

    首先我们先增加一个公用方法DoSomethingLong(string name),这个方法下面的举例中都有可能用到 #region Private Method /// <summary> ...

  4. C# 线程池ThreadPool的用法简析

    https://blog.csdn.net/smooth_tailor/article/details/52460566 什么是线程池?为什么要用线程池?怎么用线程池? 1. 什么是线程池? .NET ...

  5. C#多线程学习 之 线程池[ThreadPool]

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  6. 线程池ThreadPool实战

    线程池ThreadPool 线程池概念 常用线程池和方法 1.测试线程类 2.newFixedThreadPool固定线程池 3.newSingleThreadExecutor单线程池 4.newCa ...

  7. [转]C#多线程学习 之 线程池[ThreadPool]

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  8. 【C# 线程】线程池 ThreadPool

    Overview    如今的应用程序越来越复杂,我们常常需要使用<异步编程:线程概述及使用>中提到的多线程技术来提高应用程序的响应速度.这时我们频繁的创建和销毁线程来让应用程序快速响应操 ...

  9. 高效线程池(threadpool)的实现

    高效线程池(threadpool)的实现 Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线 ...

随机推荐

  1. VMware虚拟机 NAT模式 配置静态ip

    前言:Ubuntu 16.04 VMware虚拟机 NAT模式 配置静态ip,这个问题困扰我好长时间,桥接的静态ip我会了,然而用NAT 的方式配置集群会更好.(NAT 方式客户机之间的通讯不经过路由 ...

  2. 解决PHP无法接收post超过1000个字段的问题

    今天在做与后台交互的的过程中,发现php对于接收的POST有一个限制,超出1000个字段之后便无法接收,项目要求在不改变PHP配置的情况下通过前端方式解决,通过分析并且网上差一些大牛的资料终于找到了解 ...

  3. spring boot -- 无法读取html文件,碰到的坑

    碰到的坑,无法Controller读取html文件 1. Controller类一定要使用@Controller注解,不要用@RestController 2. resource目录下创建templa ...

  4. CSV模块

    Python csv模块的使用 1.csv简介 CSV (Comma Separated Values),即逗号分隔值(也称字符分隔值,因为分隔符可以不是逗号),是一种常用的文本 格式,用以存储表格数 ...

  5. golang 进程、线程、协程 简介

    https://www.cnblogs.com/shenguanpu/archive/2013/05/05/3060616.html https://studygolang.com/articles/ ...

  6. SQL自动生成A到Z二十六个英文字母

    if object_id('#tempdriveinfo') is not null drop table #tempdriveinfo create table #tempdriveinfo ( [ ...

  7. java 常用的解析工具

    这里介绍两种 java 解析工具. 第一种:java 解析 html 工具 jsoup 第二种: java 解析 XML 工具 Dom4j jsoup jsoup是一个用于处理真实HTML的Java库 ...

  8. Unity3D游戏开发之C#编程中常见数据结构的比较

    一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...

  9. codevs——2152 滑雪

    2152 滑雪  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description trs喜欢滑雪.他来到了一个滑雪场,这个滑雪场 ...

  10. 未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0或2.0.0.0

    未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50 ...