线程使用虚拟内存还是实际内存?


10

我正在尝试优化我的Linux服务器,使其每个进程处理10,000个线程,而现在仅处理382个线程。按照本文的说明,以下公式用于查找可能的总线程:

number of threads = total virtual memory / (stack size*1024*1024)

这意味着线程将所有数据存储在虚拟内存中。据我所知,虚拟内存是Linux机器中的交换空间,交换空间存储在硬盘上,而不是RAM或缓存。

所以我的问题是我们的线程是否使用硬盘存储来处理/存储其数据。

如果是,那么这不会影响性能吗?我们可以通过将它们放在RAM或缓存中来提高性能吗?怎么样?

如果否,线程到底如何工作?

更新:

根据无用的回答,虚拟内存是一个大致包括以下内容的系统:

  • 物理内存(RAM)
  • 您附加的所有交换文件
  • 硬件支持,用于在物理内存中不存在虚拟地址时将虚拟地址转换为物理地址并发出页面错误
  • (内核)软件支持:通过按需从交换中拉入页面来管理该硬件使用的查找表来处理那些页面错误

因此,虚拟内存上的所有内容都集中在RAM(真实内存)和硬盘(交换文件)上。正如詹姆斯在回答中所解释的那样,内核使用诸如LRU之类的算法对Ram与HDD做出了决定。


2
除非您的服务器有10,000个CPU /核,否则您将浪费时间。

@JarrodRoberson:那为什么呢?
dragosrsupercool 2012年

3
10,000个线程不是使事情扩展的好方法,这是使服务器进行爬网的好方法,每个CPU或Core超过1个线程只会使服务器上下文切换,并且运行速度变慢而不变快。

具体来说,当您说“尝试优化我的Linux服务器”时,您正在尝试优化什么?如果具有吞吐量,则每个CPU具有多路复用和无阻塞I / O的线程可能会更好。
2012年

Answers:


12

据我所知,虚拟内存是Linux机器中的交换空间

不会,虚拟内存是一个大致包含以下内容的系统:

  • 物理内存(RAM)
  • 您附加的所有交换文件
  • 硬件支持,用于在物理内存中不存在虚拟地址时将虚拟地址转换为物理地址并发出页面错误
  • (内核)软件支持:
    • 管理该硬件使用的查找表
    • 通过按需从交换中拉入页面来处理这些页面错误

取决于内核,以确保将所需的虚拟内存在需要时缓存到RAM中-除非您正在编写自己的用户空间VM层(例如数据库经常使用的iiuc),否则不必担心。


好的,所以我的虚拟内存假设是错误的。无论如何,都会有一个快速的后续问题。如果SWAP空间大于RAM,则满载的最大线程性能会受到影响吗?
dragosrsupercool 2012年

@dragosrsupercool:您的交换空间将总是大于物理内存,否则将需要使用虚拟内存。
布莱恩·奥克利

1
@BryanOakley:不一定是真的。一些操作系统为分配的每个虚拟页面分配一个交换页面(即,交换必须至少与物理页面一样大)。其他操作系统仅在需要将页面移出物理内存时(即,交换可能小于物理内存)才分配交换页面。前者的优点是,如果分配成功,则换出该内存总是成功的。后者的优点是您不需要悲观地分配巨大的交换文件来解决相对罕见的情况。
mcmcc 2012年

1
@dragosrsupercool,性能不会受到RAM数量,交换空间或它们之间的比率的影响,除非您的RAM和分页不足。sar可以告诉您有关分页活动iirc的信息(已选中:sar -B在Linux上)。
没用的2012年

@Useless:我希望增加线程数,直到我完全利用RAM并且不开始分页。
dragosrsupercool 2012年

14

如果线程实际上正在运行,则当前指令和该线程正在使用的任何变量必须位于物理内存中。

大多数(实际上几乎所有)程序都驻留在虚拟内存中,并且大多数程序使用虚拟内存来存储变量。

虚拟地址被组织为称为页面的块(通常为4096或8192字节块)。

在任何给定时间,虚拟内存的每个块都存储在实存储器中或磁盘上为此保留的“交换空间”中的某个位置。

程序代码处理虚拟地址,当您分支到虚拟地址时,或者在系统(通常在硬件级别)请求访问虚拟地址上的存储时,系统会找到地址请求的当前位置并将其映射到您的虚拟地址,如果该地址当前位于磁盘上,则会将其分页到实际内存中,然后映射该地址。

显然,如果所有物理内存都在使用中(如果要分页),则必须分页其他内容,因此系统将查找“最近最少使用”的页面,并将其复制到磁盘上,然后再复制您请求的页面。

在现代系统中,有几种与虚拟存储相关的优化和技巧。

  • 地址是按“每个进程”映射的,因此,例如,Linux盒中的所有C程序都在同一地址启动“主”进程。
  • 由于32位虚拟地址可以映射到真实的64位地址,因此这可以使几个32位进程在计算机上占用并使用的内存超过4GB。
  • 当进程结束或以其他方式“释放”内存时,系统仅将页面标记为空闲,因此它们永远不会复制回交换磁盘。
  • 类似地,当请求新的存储块时,系统仅获取实际内存中的空闲页,否,发生磁盘IO。
  • sleep和hibernate函数强制将所有内存复制到交换空间,以便在唤醒时可以重新创建所有当前进程以及那里的当前内存内容。

3
“ Linux盒子中的所有C程序[main]都在同一地址开始”似乎没有考虑地址空间布局的随机性。今天,越来越多的人使用它来阻止各种堆栈破坏攻击方案。否则,请回答好,所以+1。
CVn 2012年

7

首先,您需要阅读有关计算机内存的更多信息,因为您似乎缺少该领域的知识。

执行线程是操作系统可以调度的最小处理单元。线程和进程的实现因一个操作系统而异,但在大多数情况下,线程包含在进程内部。多个线程可以存在于同一进程中并共享诸如内存的资源,而不同的进程则不共享这些资源。

因此,线程将使用可用的内存-任何可用的内存。您可以启动多少个线程取决于内存大小以及每个线程需要多少内存。如果线程使用堆(不仅是堆栈),那么它需要更多的内存,在这种情况下,您可以启动更少的线程。


@VJonvic:+1为基本线程说明。
dragosrsupercool 2012年

6

您问题的简单答案是,它们使用虚拟内存。除少数与操作系统相关的进程外,所有事物都使用虚拟内存。

另一方面,当您的线程(或任何进程中的任何线程)实际运行时,它正在使用物理内存。与该进程关联的内存页面被交换到处理器执行工作的物理内存中。


3

虚拟内存是您的RAM 交换空间。虚拟正义意味着您的程序看到的地址与RAM芯片看到的地址不同。如果您需要交换访问内存,操作系统将首先将其移至RAM。如果您不想进行任何交换,只需禁用它即可。如果您有足够的RAM,那么您实际上就不需要它。

话虽如此,除非您拥有10,000个核心处理器,否则增加到10,000个线程并不是真正的“优化”。一旦有足够的线程来消耗所有内核,再加上一两个备用线程(当这些线程被阻塞时),由于切换开销和高速缓存未命中,添加更多线程会降低性能。如果它可以使程序逻辑更简单,则可能仍要使用更多线程,但是您将在性能上进行权衡。


是的,因为我的服务器是32位单核计算机,所以10,000太多了。实际上,线程不是总的cpu的东西。它们是搜寻器线程,因此有时就像等待服务器响应一样。我的目的是确保CPU完全被占用,但不会过载或欠载。但是我仍然不明白如何知道CPU是空闲还是完全被占用。有任何工具或命令吗?
dragosrsupercool 2012年

我认为您可以从top命令中获取该信息。
Karl Bielefeldt 2012年

@KarlBieledeldt:是的,这正是我所要的。在不使用太多线程的情况下,CPU利用率很高。那可能吗?就像从一个线程发送请求同时在另一线程上接收响应一样?
dragosrsupercool 2012年

2

优化我的Linux服务器以每个进程处理10,000个线程

正如其他人解释的那样,这通常是错误的。一个线程是一个昂贵的资源,特别是因为它有自己的调用堆栈(通常是兆字节),因为它是由内核任务调度。线程比打开的文件描述符更昂贵。

阅读操作系统:三篇简单的文章(可免费下载的教科书)。

根据经验,您不希望有很多线程,当然也不希望有很多可运行线程。可运行线程的数量通常最多应为核心数量(或核心数量的一小部分),因此最多为十二个。进程中的线程数可能会稍大。因此,除非您拥有一台非常昂贵的服务器(具有许多处理器插槽和内核),否则您不希望在进程中(在桌面上)有超过十二个可运行线程,以及一百个线程(其中大多数处于空闲状态) 。

在Linux上,线程和进程非常相似(因为两者都可以由clone(2)创建),并且都是内核计划的任务。实际上,内核调度程序正在调度任务,这些任务可以是某些多线程进程中的线程,也可以是单线程进程的单个主线程(在这种情况下,您将命名为“进程”那个单线程)或内核线程。您可能不希望桌面系统上总共有超过一千个可调度的任务。

在Linux上,进程只是一组共享相同虚拟地址空间(并共享其他内容,例如文件描述符表等)的线程。有些进程只有一个线程。

虚拟地址空间限定通过维基百科

“操作系统可用于进程的一组虚拟地址范围”

(也看到这个答案解释的术语是不具有普遍性,一些微软的文档使用不同的不兼容的定义)。

在Linux上,proc(5)对于了解某些进程的虚拟地址空间很有用。尝试都
cat /proc/self/mapscat /proc/$$/maps一个终端。另请参见thispmap(1)ps(1)top(1)

所有用户空间程序都在某个进程中运行并且正在使用虚拟内存,因此每个进程都有自己的虚拟地址空间。物理RAM是由Linux内核管理的资源,应用程序无法直接访问RAM(mmap(2) -ing 除外/dev/mem,请参阅mem(4))。

因此,进程不直接使用RAM。它使用虚拟内存并具有自己的虚拟地址空间。该内核采用分页来管理物理内存,并提供虚拟地址空间和过程的抽象。在任何时候(即使您的进程处于空闲状态或正在运行时),内核都可以调出某些页面(例如,在磁盘上交换它们)。内核正在配置MMU(并通过从磁盘获取页面或将分段错误传播到进程中来处理某些中断处理程序中的页面遗漏硬件异常,请参见signal(7)

您可能在系统线程之上有绿色线程(但是绿色线程库很难实现和调试)。看一下Go中使用的goroutines例子。另请参见setcontext(3)

有时,您的系统可能会尝试抖动。当虚拟内存总量(所有进程都需要)超过可用物理RAM很大时,就会发生这种情况。然后您的计算机变得无响应。阅读有关常驻集大小需求分页工作集内存过量使用ASLR的信息

另请参见-for Linux- fork(2)clone(2)mmap(2)madvise(2)posix_fadvise(2)mlock(2)execve(2)凭据(7)pthreads(7)futex(7)功能(7)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.