全栈软件测试工程师宝典连载(9)

简介: 全栈软件测试工程师宝典连载(9)

2. 内存


1)内核空间、用户空间

Linux内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。Linux的空间又分为内核空间和用户空间,在32位中,内核空间占1G,用户空间占3G;而在64位中,内核空间和用户空间各占128T。如图3-24所示。


image.png

3-24  Linux内存空间


2)内核映射

Linux不会直接访问物理内存地址,而是访问虚拟地址。内存映射,就是将虚拟内存地址映射到物理内存地址。而当进程访问的虚拟地址在页表中查不到的时候,系统会产生一个缺页异常,进入内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。内核映射如图3-25所示。


image.png

3-25  内核映射


3)虚拟内存空间分布

虚拟内存空间分布以32位为例,如图3-26所示。

image.png

3-26  虚拟内存空间分布(以32位为例)


从下到上依次为只读段、数据段、堆、文件映射和栈五部分组成。

栈。

包括局部变量和函数调用的上下文等。栈的大小是固定的,一般为8MB

文件映射段。

包括动态分配的内存,从低地址开始向上增长。

堆。

包括动态分配的内存,从低地址开始向上增长。

数据段。

数据段。

只读段。

包括代码和常量。

堆和文件映射段的内存是动态分配的,可以使用C标准库的malloc()或者mmap()方法进行分配。


4)内存的分配和释放
内存分配

[33]malloc()C语言提供的内存分配方法,有两种实现方式:brk()mmap()

对小块内存是指≤128K的内存,C语言使用 brk()函数来分配,它通过移动堆顶的位置来分配内存。这些内存释放后并不会马上还给系统,而是被缓存起来,就可以重复使用了。brk()函数的缓存,可以减少缺页异常的发生,从而提高内存访问的效率。但是由于这些内存没有还给系统,在内存工作繁忙的时候,频繁的内存分配和释放会造成大量的内存碎片。

大块内存是指>128K的内存,使用内存映射mmap()函数来分配,它在文件映射段找一块空闲内存分配出去。mmap()方式分配的内存,可以在释放时直接归还系统,所以每次 mmap都会发生缺页异常。在内存工作繁忙的时候,频繁的内存分配会导致大量的缺页异常,使内核的管理工作加大。这也正是malloc仅对大块内存使用mmap的原因。


内存回收

对于回收,有以下几种策略。

FIFOFirst In First Out)。

先进先出算法,即先放入缓存的先被移除。

LRULeast Recently Used)。

最近最少使用算法,离现在时间最久的先被移除。

LFULeast Frequently Used)。

最不常用算法,一定时间段内使用【次数(频率)】最少的先被移除。

Linux的内存回收一般分为以下三种方式。

使用LRULeast Recently Used)回收最近最少使用的缓存。

•通过LFU算法,把不常用的内存通过交换分区(Swap:把硬盘空间作为内存使用的机制)直接写到磁盘中。

杀死进程,内存紧张时系统通过OOMOut of Memory),直接杀掉占用大量内存的进程。


在这里简单介绍一下OOMLinux内核根据应用程序的要求来分配内存,应用程序分配了内存可能没有实际全部使用,为了提高性能,这部分没用的内存可以留作其他用途,由于这部分内存是属于每个进程的,内核直接回收利用会带来麻烦,所以内核采用一种过度分配内存(over-commit memory)的机制来间接利用这部分“空闲”的内存,来提高整体内存的使用效率。一般来说这样是没有问题的,但是当大多数应用程序都消耗完自己的内存的时候就有问题了,因为这些应用程序的内存需求之和超出了物理内存(包括SWAP)的容量,内核必须杀掉一些进程才能产生空间来保障系统的正常运行。Linux内核的这种机制叫做OOMkillerOut-Of-Memorykiller),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽内核会把该进程杀掉。在OOM中,使用oom_score来为每个进程的内存使用情况进行评分。


一个进程消耗的内存越大,oom_score就越大。

一个进程运行占用的CPU越多,oom_score 就越小。


当进程的oom_score 越大,表示消耗的内存越多,也就越容易被OOM杀死,从而可以更好保护系统。也可以通过oom_adj来调整oom_scoreoom_adj的范围是[-17, 15],数值越大,表示进程越容易被OOM杀死;数值越小,表示进程越不容易被OOM杀死,其中-17表示禁止OOMoom_adj位于/proc/$(pidof sshd)/oom_adj,可以通过


#echo -16 > /proc/$(pidof sshd)/oom_adj


来设置。也可以通过

# cat /proc/$(pidof sshd)/oom_adj
-16

来获得。


5)查看内存使用情况

可以通过命令free来查看内存使用情况。

# free
            total       used          free         shared    buff/cache  available
Mem:       4312648     1577592      210964       18624    2524092       2426060
Swap:      969960      1036          968924


其参数参考表3-7所示。


3-7 freet命令输出详解

标识

含义

total

总内存大小

used

已使用内存的大小,包含了共享内存

free

未使用内存的大小

shared

共享内存的大小

buff/cache

缓存和缓冲区的大小

available

新进程可用内存的大小


注意:在这里available不仅包含未使用内存,还包括了可回收的缓存。查看内存瓶颈并非看free即可。


也可以用top命令的第45行及进程部分来查看内存的使用情况。


#top
KiB Mem : 4312648 total,   107164 free,  1584800 used, 2620684 buff/cache
KiB Swap:  969960 total,   968924 free,  1036 used.     2417764 avail Mem
 PID    USER  PR   NI    VIRT   RES     SHR   S  %CPU %MEM TIME+ COMMAND                                                                                                                               
 20864root    20   0   4784     1520    1236  R  98.00.0   0:03.34 gzip                                                                                                                                  
 2044  jerry  20   0    3745868  204216 79064 S 8.9  4.7   1:13.52 gnome-shell                                                                                                                            
 20866root    20   0    14696   812     748    S  6.3 0.0   0:00.22 cpio                                                                                                                                  
 1915  jerry  20   0    462104   86288   47384S  4.6 2.0   0:26.55 Xorg                                                                                                                                  
 2416  jerry  20   0    730376   38900   27232S  3.0 0.9   0:14.85 gnome-terminal-                                                                                                                       
 22     root   20   0    0        0       0       S 2.6  0.0   0:00.50 ksoftirqd/2

top命令第45行其参数请参考表3-8


3-8 top命令中第45行参数含义

标识

解释

Mem:###k total

物理内存总量

Mem:###k used

使用的物理内存总量

Mem: ###k free

空闲内的存总量

Mem:###k buffers

用作内核缓存的内存总量

Swap: ###k total

交换区的总量

Swap: ###k used

使用的交换区总量

Swap: ###k free

空闲的交换区总量

Swap: ###k cached

缓冲的交换区总量


top命令进程中关于内存性能如表3-9所示。


3-9 top命令进程中关于内存性能参数

标记

解释

VIRT

进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。

RES

常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。

SHR

共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。

%MEM

进程使用物理内存占系统总内存的百分比。


6cachebuffer

cachebuffer中文翻译都叫缓冲或缓存,但是他们是由区别的。

cache是缓存从文件读写的信息。

buffer是缓存从硬盘读写的信息。


可以通过cachestatcachetop来查看cache信息(这两个命令都需要先安装bcc包,由于每种Linux的安装方法都不同,这里不进行介绍,读者可到网上下载安装)。cachestat提供了整个操作系统缓存的读写命中情况,cachetop提供了每个进程的缓存命中情况。缓存命中率是指直接通过缓存获取数据的请求次数与占所有数据请求次数的百分比。命中率越高,表示使用缓存带来的收益越高,应用程序的性能当然也越好。

# cachestat 1 3
  TOTAL   MISSES     HITS DIRTIES   BUFFERS_MB  CACHED_MB
   2        0         2      1         17          279
   2        0         2      1         17          279
   2        0         2      1         17          279 


参数请查看表3-10所示。


3-10 cachestat参数

标记

解释

TOTAL

总的 I/O 次数

MISSES

缓存未命中的次数

HITS

缓存命中的次数

DIRTIES

新增到缓存中的脏页数

BUFFERS_MB

Buffers 的大小,以 MB 为单位

CACHED_MB

Cache 的大小,以 MB 为单位


# cachetop
11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort:HITS / Order: ascending
PID     UID      CMD              HITS     MISSES  DIRTIES  READ_HIT%  WRITE_HIT%
13029     root     python         1        0         0         100.0%      0.0%

其中READ_HITWRITE_HIT,分别表示读和写的缓存命中率。


7SWAP机制

SWAP是把系统硬盘作为内存使用的一种机制。Linux上可以使用swapon -s命令查看当前系统中正在使用的交换空间和相关信息。

# swapon -s
FilenameTypeSize      Used Priority
/swapfile    file    9699604620  -2


系统通过参数swappiness来控制SWAP积极程度,可以通过。


# cat /proc/sys/vm/swappiness
60


来查看,这个值在0100之间,默认为60。数值越大,说明越积极使用 SWAP;数值越小,说明越消极使用 SWAP注意:但是并不是说swappiness=0,就不进行SWAP,而是使用SWAP的积极性。可以通过vmstat命令来查看系统的SWAP情况。

# vmstat
procs-----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b  swpd   free        buff   cache       si   so   bi     bo    in    cs    us   sy id wa st
0  0 10336  287032      16856  266904      0    9     556    278   155   452   15    4  79 2  0


其参数请查看表3-11所示。


3-11 vmstat参数

标记

解释

swpd

已经使用的交换内存(kb

free

空闲的物理内存(kb

buff

用作缓冲区的内存数(kb),暂存的数据

cache

用作高速缓存的内存数(kb),将最近使用过的文件放在内存中

si

自上次取样以来从磁盘交换出来的比特数

so

自上次取样以来交换到磁盘的比特数


在这里siso即为SWAP的数据。如图3-27所示,站在内存的角度来看si指的是从磁盘分配给内存的比特数,so表示内存还给硬盘的比特数。


image.png

3-27  虚拟内存空间分配


扩展阅读:SAWP内存回收机制

直接内存回收(静态回收)。当有大内存提出申请,直接回收内存。

kswap0内存回收(动态回收)。pages_min 存储在/proc/sys/vm/min_free_kbytes中。

# cat /proc/sys/vm/min_free_kbytes38488


pages_low = pages_min × 5/4pages_high  = pages_min × 3/2。参见图3-28所示。

微信图片_20230213221328.png

3-28  swap0内存回收


纵坐标为有一个进程pages_free,表示内存使用情况。每隔一段时间进行扫描,当发现当前pages_free<pages_low,就发起内存回收。


8)系统内存摘要信息

仍旧可以使用vmstat来查看系统内存摘要信息。

# vmstat -s
     4312648 K total memory
     1589480 K used memory
     1764644 K active memory
     1107684 K inactive memory
      625492 K free memory
       22880 K buffer memory
     2074796 K swap cache
      969960 K total swap
        4620 K used swap
      965340 K free swap
       81312 non-nice user cpu ticks
       27207 nice user cpu ticks
       56108 system cpu ticks
     4871600 idle cpu ticks
        7258 io-wait cpu ticks
           0 IRQ cpu ticks
        3317 softirq cpu ticks
           0 stolen cpu ticks
     2337551 pages paged in
     8028020 pages paged out
          16 pages swapped in
        1001 pages swapped out
     3218309 interrupts
      4614976 CPU context switches
  1575877682 boot time
       49574 forks


9)显示某个进程所用的内存情况

可以使用pmap 来查看某个进程所用的内存情况。

# pmap 3785
3785:  /usr/bin/python3 manage.py runserver 0.0.0.0:8000 --insecure
0000000000400000  3792K r-x-- python3.6
00000000009b3000      4K r---- python3.6
00000000009b4000   628K rw--- python3.6
0000000000a51000   204K rw---   [ anon ]
0000000000eba000  5236K rw---   [ anon ]
00007ff6e8000000   644K rw---   [ anon ]
00007ff6e80a1000 64892K -----   [ anon ]
00007ff6eca72000     44K r-x-- libnss_files-2.27.so
00007ff6eca7d000  2044K ----- libnss_files-2.27.so
00007ff6ecc7c000      4K r---- libnss_files-2.27.so
00007ff6ecc7d000      4K rw--- libnss_files-2.27.so
00007ff6ecc7e000  2588K rw---   [ anon ]
00007ff6ecf05000      4K -----  [ anon ]
00007ff6ecf06000  9984K rw---   [ anon ]


10)显示10个消耗内存最多的进程

CPU一样,也可以通过命令来显示10个消耗内存最多的进程。

# ps aux|sort -rnk +4|head -10
jerry    49301  0.3  4.2 921596 181256 tty2    SNl+ 02:25  0:13 /usr/bin/python3 /usr/bin/update-manager --no-update--no-focus-on-map
jerry     2264  0.1  3.7 1399412 160552 tty2   SLl+ Dec08  0:18 /usr/bin/gnome-software --gapplication-service
jerry     2044  0.8  3.7 3747824 162252 tty2   Sl+ Dec08   1:45 /usr/bin/gnome-shell
gdm       1024  0.1  2.1 3378676 91928 tty1    Sl+ Dec08   0:13 /usr/bin/gnome-shell
jerry     2260  0.0  2.0 1078900 90292 tty2    Sl+ Dec08   0:06 nautilus-desktop
jerry     1915  0.2  1.5 463272 64864 tty2     Sl+ Dec08   0:35 /usr/lib/xorg/Xorgvt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset-keeptty -verbose 3
jerry     2306  0.0  1.2 892092 53404 ?        Ssl Dec08   0:01 /usr/lib/evolution/evolution-calendar-factory
root      1324  0.2  1.1 522060 49556 ?        Ssl Dec08   0:29 /usr/lib/packagekit/packagekitd
jerry     2335  0.0  1.1 1135836 50004 ?       Sl  Dec08   0:01 /usr/lib/evolution/evolution-calendar-factory-subprocess--factory all --bus-name org.gnome.evolution.dataserver.Subprocess.Backend.Calendarx2306x2--own-path /org/gnome/evolution/dataserver/Subprocess/Backend/Calendar/2306/2
jerry     3785  1.4  0.8 176328 36240 pts/1    Sl+ 00:14   2:46 /usr/bin/python3manage.py runserver 0.0.0.0:8000 –insecure


11)小结

本节所涉及的概念有内核空间和用户空间、内核映射、虚拟内存空间分布、内存的分配和释放、查看内存使用情况、cachebufferSWAP机制。涉及到的命令有echo -16 > /proc/$(pidofsshd)/oom_adjcat /proc/$(pidofsshd)/oom_adjfreetopcachestatcachetopswaponcat /proc/sys/vm/swappinesvmstatcat/proc/sys/vm/min_free_kbytespmap ps aux|sort -rnk +4|head -10

目录
相关文章
|
6月前
|
机器学习/深度学习 人工智能 算法
新时代软件测试工程师的挑战与机遇
随着科技的飞速发展,软件测试在当今信息化社会中扮演着举足轻重的角色。本文将探讨新时代软件测试工程师所面临的挑战和机遇,分析其发展趋势及应对策略,旨在为广大软件测试从业人员提供启示和指导。
|
测试技术 数据库
腾讯游戏测试工程师的经验心得分享
腾讯游戏测试工程师的经验心得分享
412 0
|
18天前
|
编解码 安全 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(10-2):保姆级别教会你如何搭建白帽黑客渗透测试系统环境Kali——Liinux-Debian:就怕你学成黑客啦!)作者——LJS
保姆级别教会你如何搭建白帽黑客渗透测试系统环境Kali以及常见的报错及对应解决方案、常用Kali功能简便化以及详解如何具体实现
|
1月前
|
Java 测试技术 程序员
「测试线排查的一些经验-上篇」&& 后端工程师
「测试线排查的一些经验-上篇」&& 后端工程师
16 1
|
18天前
|
人工智能 安全 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(4-2):渗透测试行业术语扫盲完结:就怕你学成黑客啦!)作者——LJS
网络空间安全之一个WH的超前沿全栈技术深入学习之路(4-2):渗透测试行业术语扫盲完结:就怕你学成黑客啦!)作者——LJS
|
18天前
|
安全 大数据 Linux
网络空间安全之一个WH的超前沿全栈技术深入学习之路(3-2):渗透测试行业术语扫盲)作者——LJS
网络空间安全之一个WH的超前沿全栈技术深入学习之路(3-2):渗透测试行业术语扫盲)作者——LJS
|
18天前
|
SQL 安全 网络协议
网络空间安全之一个WH的超前沿全栈技术深入学习之路(1-2):渗透测试行业术语扫盲)作者——LJS
网络空间安全之一个WH的超前沿全栈技术深入学习之路(1-2):渗透测试行业术语扫盲)作者——LJS
|
3月前
|
算法
测试工程师的技能升级:LeetCode算法挑战与职业成长
这篇文章通过作者亲身体验LeetCode算法题的过程,探讨了测试工程师学习算法的重要性,并强调了算法技能对于测试职业成长的必要性。
68 1
测试工程师的技能升级:LeetCode算法挑战与职业成长
|
3月前
|
运维 测试技术
测试与开发问题之测试开发工程师与软件开发工程师和测试工程师如何区别
测试与开发问题之测试开发工程师与软件开发工程师和测试工程师如何区别
|
3月前
|
监控 安全 测试技术
测试与开发问题之为什么测试开发工程师需要有安全生产意识,文档编写能力对于测试开发工程师的重要性如何理解
测试与开发问题之为什么测试开发工程师需要有安全生产意识,文档编写能力对于测试开发工程师的重要性如何理解

热门文章

最新文章