📄 csdn_文档中心_vc++多线程下内存操作的优化.htm
字号:
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在高负荷下有上千次的上下文切换是正常的,但当计数超过</SPAN><SPAN
lang=EN-US>80,000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或</SPAN><SPAN
lang=EN-US>100,000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时,说明过多的时间都浪费在线程的切换,稍微计算一下就可以知道,如果每秒有</SPAN><SPAN
lang=EN-US>100,000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">次线程切换,则每个线程只有</SPAN><SPAN
lang=EN-US>10</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">微秒用于运行,而</SPAN><SPAN
lang=EN-US>NT</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上的正常的时间片长度约有</SPAN><SPAN
lang=EN-US>12</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">毫秒,是前者的上千倍。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">图</SPAN><SPAN
lang=EN-US>1</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的性能图显示了过度的线程切换,而图</SPAN><SPAN
lang=EN-US>2</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">显示了同一个进程在同样的环境下,在使用了下面提供的解决方法后的情况。图</SPAN><SPAN
lang=EN-US>1</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的情况下,系统每秒钟要进行</SPAN><SPAN
lang=EN-US>120,000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">次线程切换,改进后,每秒钟线程切换的次数减少到</SPAN><SPAN
lang=EN-US>1,000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">次以下。两张图都是在运行同一个测试程序时截取得,程序中同时有</SPAN><SPAN
lang=EN-US>3</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个线程同时进行最大为</SPAN><SPAN
lang=EN-US>2</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,</SPAN><SPAN
lang=EN-US>048</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">字节的堆的申请,硬件平台是一个双</SPAN><SPAN
lang=EN-US>Pentium II 450</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">机器,有</SPAN><SPAN
lang=EN-US>256MB</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">内存。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
<P class=MsoNormal><B><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">解决方法</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本方法要求多线程程序是用</SPAN><SPAN
lang=EN-US>VC++</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编写的,并且是动态链接到</SPAN><SPAN
lang=EN-US>C</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行库的。要求</SPAN><SPAN
lang=EN-US>NT</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系统所安装的</SPAN><SPAN
lang=EN-US>VC++</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行库文件</SPAN><SPAN
lang=EN-US>msvcrt.dll</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的版本号是</SPAN><SPAN
lang=EN-US>6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,所安装的</SPAN><SPAN
lang=EN-US>service pack</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的版本是</SPAN><SPAN
lang=EN-US>5</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以上。如果程序是用</SPAN><SPAN
lang=EN-US>VC++ v6.0</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以上版本编译的,即使多线程程序和</SPAN><SPAN
lang=EN-US>libcmt.lib</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是静态链接,本方法也可以使用。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当一个</SPAN><SPAN
lang=EN-US>VC++</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序运行时,</SPAN><SPAN
lang=EN-US>C</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行库被初始化,其中一项工作是确定要使用的堆管理器,</SPAN><SPAN
lang=EN-US>VC++ v6.0</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行库既可以使用其自己内部的堆管理函数,也可以直接调用操作系统的堆管理函数(</SPAN><SPAN
lang=EN-US>HeapAlloc()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系列的函数),在</SPAN><SPAN
lang=EN-US>__heap_select()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数内部分执行以下三个步骤:</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN>1</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、检查操作系统的版本,如果运行于</SPAN><SPAN
lang=EN-US>NT</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,并且主版本是</SPAN><SPAN
lang=EN-US>5</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或更高(</SPAN><SPAN
lang=EN-US>Window 2000</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">及以后版本),就使用</SPAN><SPAN
lang=EN-US>HeapAlloc()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN>2</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、查找环境变量</SPAN><SPAN
lang=EN-US>__MSVCRT_HEAP_SELECT</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,如果有,将确定使用哪个堆函数。如果其值是</SPAN><SPAN
lang=EN-US>__GLOBAL_HEAP_SELECTED</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,则会改变所有程序的行为。如果是一个可执行文件的完整路径,还要调用</SPAN><SPAN
lang=EN-US>GetModuleFileName()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">检查是否该程序存在,至于要选择哪个堆函数还要查看逗号后面的值,</SPAN><SPAN
lang=EN-US>1</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示使用</SPAN><SPAN
lang=EN-US>HeapAlloc()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">,</SPAN><SPAN
lang=EN-US>2</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示使用</SPAN><SPAN
lang=EN-US>VC++ v5</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的堆函数,</SPAN><SPAN
lang=EN-US>3</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示使用</SPAN><SPAN
lang=EN-US>VC++ v6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的堆函数。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN>3</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、检测可执行文件中的链接程序标志,如果是由</SPAN><SPAN
lang=EN-US>VC++ v6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或更高的版本创建的,就使用版本</SPAN><SPAN
lang=EN-US>6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的堆函数,否则使用版本</SPAN><SPAN
lang=EN-US>5</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的堆函数。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">那么如何提高程序的性能?如果是和</SPAN><SPAN
lang=EN-US>msvcrt.dll</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">动态链接的,保证这个</SPAN><SPAN
lang=EN-US>dll</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是</SPAN><SPAN
lang=EN-US>1999</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">年</SPAN><SPAN
lang=EN-US>2</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">月以后,并且安装的</SPAN><SPAN
lang=EN-US>service pack</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的版本是</SPAN><SPAN
lang=EN-US>5</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或更高。如果是静态链接的,保证链接程序的版本号是</SPAN><SPAN
lang=EN-US>6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或更高,可以用</SPAN><SPAN
lang=EN-US>quickview.exe</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序检查这个版本号。要改变所要运行的程序的堆函数的选取,在命令行下键入以下命令:</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal
style="TEXT-INDENT: 21pt; mso-char-indent-count: 2.0; mso-char-indent-size: 10.5pt"><SPAN
lang=EN-US>set
__MSVCRT_HEAP_SELECT=__GLOBAL_HEAP_SELECTED,1<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US><SPAN
style="mso-spacerun: yes"> </SPAN></SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以后,所有从这个命令行运行的程序,都会继承这个环境变量的设置。这样,在堆操作时都会使用</SPAN><SPAN
lang=EN-US>HeapAlloc()</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。如果让所有的程序都使用这些速度更快的堆操作函数,运行控制面板的“系统”程序,选择“环境”,点取“系统变量”,输入变量名和值,然后按“应用”按钮关闭对话框,重新启动机器。</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal style="TEXT-INDENT: 21pt"><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按照微软的说法,可能有一些用</SPAN><SPAN
lang=EN-US>VC++ v6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以前版本编译程序,使用</SPAN><SPAN
lang=EN-US>VC++ v6</SPAN><SPAN
style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的堆管理器会出现一些问题。如果在进行以上设置后遇到这样的问题,可以用一个批处理文件专门为这个程序把这个设置去掉,例如:</SPAN><SPAN
lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal
style="TEXT-INDENT: 10.5pt; mso-char-indent-count: 1.0; mso-char-indent-size: 10.5pt"><SPAN
lang=EN-US>set __MSVCRT_HEAP_SELECT=c:\program
files\myapp\myapp.exe,1 c:\bin\buggyapp.exe,2<o:p></o:p></SPAN></P>
<P class=MsoNormal><SPAN lang=EN-US> <o:p></o:p></SPAN></P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -