linux memcpy性能优化_Linux性能优化从入门到精通(一)

分析系统瓶颈

系统响应变慢,首先得定位大致的问题出在哪里,是IO瓶颈、CPU瓶颈、内存瓶颈还是程序导致的系统问题;

使用top工具能够比较全面的查看我们关注的点:

$top    top - 09:14:56 up 264 days, 20:56,  1 user,  load average: 0.02, 0.04, 0.00    Tasks:  87 total,   1 running,  86 sleeping,   0 stopped,   0 zombie    Cpu(s):  0.0%us,  0.2%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.2%st    Mem:    377672k total,   322332k used,    55340k free,    32592k buffers    Swap:   397308k total,    67192k used,   330116k free,    71900k cached    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND    1 root      20   0  2856  656  388 S  0.0  0.2   0:49.40 init    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd    3 root      20   0     0    0    0 S  0.0  0.0   7:15.20 ksoftirqd/0    4 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/

进入交互模式后:

  • 输入M,进程列表按内存使用大小降序排序,便于我们观察最大内存使用者使用有问题(检测内存泄漏问题);
  • 输入P,进程列表按CPU使用大小降序排序,便于我们观察最耗CPU资源的使用者是否有问题;

top第三行显示当前系统的,其中有两个值很关键:

  • %id:空闲CPU时间百分比,如果这个值过低,表明系统CPU存在瓶颈;
  • %wa:等待I/O的CPU时间百分比,如果这个值过高,表明IO存在瓶颈;
c9cb1084dea7fecaf4952f065d36f9b8.png

分析内存瓶颈

查看内存是否存在瓶颈,使用top指令看比较麻烦,而free命令更为直观:

[/home/weber#]free             total       used       free     shared    buffers     cachedMem:        501820     452028      49792      37064       5056     136732-/+ buffers/cache:     310240     191580Swap:            0          0          0[/home/weber#]toptop - 17:52:17 up 42 days,  7:10,  1 user,  load average: 0.02, 0.02, 0.05Tasks:  80 total,   1 running,  79 sleeping,   0 stopped,   0 zombie%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 stKiB Mem:    501820 total,   452548 used,    49272 free,     5144 buffersKiB Swap:        0 total,        0 used,        0 free.   136988 cached Mem

top工具显示了free工具的第一行所有信息,但真实可用的内存,还需要自己计算才知道; 系统实际可用的内存为free工具输出第二行的free+buffer+cached;也就是第三行的free值191580;关于free命令各个值的详情解读,请参考这篇文章 free 查询可用内存 ;

如果是因为缺少内存,系统响应变慢很明显,因为这使得系统不停的做换入换出的工作;

进一步的监视内存使用情况,可使用vmstat工具,实时动态监视操作系统的内存和虚拟内存的动态变化。 参考: vmstat 监视内存使用情况 ;

分析IO瓶颈

如果IO存在性能瓶颈,top工具中的%wa会偏高;

进一步分析使用iostat工具:

/root$iostat -d -x -k 1 1Linux 2.6.32-279.el6.x86_64 (colin)   07/16/2014      _x86_64_        (4 CPU)Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %utilsda               0.02     7.25    0.04    1.90     0.74    35.47    37.15     0.04   19.13   5.58   1.09dm-0              0.00     0.00    0.04    3.05     0.28    12.18     8.07     0.65  209.01   1.11   0.34dm-1              0.00     0.00    0.02    5.82     0.46    23.26     8.13     0.43   74.33   1.30   0.76dm-2              0.00     0.00    0.00    0.01     0.00     0.02     8.00     0.00    5.41   3.28   0.00
  • 如果%iowait的值过高,表示硬盘存在I/O瓶颈。
  • 如果 %util 接近 100%,说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈。
  • 如果 svctm 比较接近 await,说明 I/O 几乎没有等待时间;
  • 如果 await 远大于 svctm,说明I/O 队列太长,io响应太慢,则需要进行必要优化。
  • 如果avgqu-sz比较大,也表示有大量io在等待。

更多参数说明请参考 iostat 监视I/O子系统 ;

分析进程调用

通过top等工具发现系统性能问题是由某个进程导致的之后,接下来我们就需要分析这个进程;继续 查询问题在哪;

这里我们有两个好用的工具: pstack和pstrace

pstack用来跟踪进程栈,这个命令在排查进程问题时非常有用,比如我们发现一个服务一直处于work状态(如假死状态,好似死循环),使用这个命令就能轻松定位问题所在;可以在一段时间内,多执行几次pstack,若发现代码栈总是停在同一个位置,那个位置就需要重点关注,很可能就是出问题的地方;

示例:查看bash程序进程栈:

/opt/app/tdev1$ps -fe| grep bashtdev1   7013  7012  0 19:42 pts/1    00:00:00 -bashtdev1  11402 11401  0 20:31 pts/2    00:00:00 -bashtdev1  11474 11402  0 20:32 pts/2    00:00:00 grep bash/opt/app/tdev1$pstack 7013#0  0x00000039958c5620 in __read_nocancel () from /lib64/libc.so.6#1  0x000000000047dafe in rl_getc ()#2  0x000000000047def6 in rl_read_key ()#3  0x000000000046d0f5 in readline_internal_char ()#4  0x000000000046d4e5 in readline ()#5  0x00000000004213cf in ?? ()#6  0x000000000041d685 in ?? ()#7  0x000000000041e89e in ?? ()#8  0x00000000004218dc in yyparse ()#9  0x000000000041b507 in parse_command ()#10 0x000000000041b5c6 in read_command ()#11 0x000000000041b74e in reader_loop ()#12 0x000000000041b2aa in main ()

而strace用来跟踪进程中的系统调用;这个工具能够动态的跟踪进程执行时的系统调用和所接收的信号。是一个非常有效的检测、指导和调试工具。系统管理员可以通过该命令容易地解决程序问题。

参考: strace 跟踪进程中的系统调用 ;

优化程序代码

优化自己开发的程序,建议采用以下准则:

  1. 二八法则:在任何一组东西中,最重要的只占其中一小部分,约20%,其余80%的尽管是多数,却是次要的;在优化实践中,我们将精力集中在优化那20%最耗时的代码上,整体性能将有显著的提升;这个很好理解。函数A虽然代码量大,但在一次正常执行流程中,只调用了一次。而另一个函数B代码量比A小很多,但被调用了1000次。显然,我们更应关注B的优化。
  2. 编完代码,再优化;编码的时候总是考虑最佳性能未必总是好的;在强调最佳性能的编码方式的同时,可能就损失了代码的可读性和开发效率;

gprof使用步骤

  1. 用gcc、g++、xlC编译程序时,使用-pg参数,如:g++ -pg -o test.exe test.cpp编译器会自动在目标代码中插入用于性能测试的代码片断,这些代码在程序运行时采集并记录函数的调用关系和调用次数,并记录函数自身执行时间和被调用函数的执行时间。
  2. 执行编译后的可执行程序,如:./test.exe。该步骤运行程序的时间会稍慢于正常编译的可执行程序的运行时间。程序运行结束后,会在程序所在路径下生成一个缺省文件名为gmon.out的文件,这个文件就是记录程序运行的性能、调用关系、调用次数等信息的数据文件。
  3. 使用gprof命令来分析记录程序运行信息的gmon.out文件,如:gprof test.exe gmon.out则可以在显示器上看到函数调用相关的统计、分析信息。上述信息也可以采用gprof test.exe gmon.out> gprofresult.txt重定向到文本文件以便于后续分析。

关于gprof的使用案例,请参考 [f1] ;

其它工具

调试内存泄漏的工具valgrind,感兴趣的朋友可以google了解;

OProfile: Linux 平台上的一个功能强大的性能分析工具,使用参考 [f2] ;

除了上面介绍的工具,还有一些比较全面的性能分析工具,比如sar(Linux系统上默认不安装,需要手动安装下); 将sar的常驻监控工具打开后,能够收集比较全面的性能分析数据;

vmstat命令

性能监测与优化

vmstat命令的含义为显示虚拟内存状态(“Virtual Memory Statistics”),但是它可以报告关于进程、内存、I/O等系统整体运行状态。

语法

vmstat(选项)(参数)

选项

-a:显示活动内页;-f:显示启动后创建的进程总数;-m:显示slab信息;-n:头信息仅显示一次;-s:以表格方式显示事件计数器和内存状态;-d:报告磁盘状态;-p:显示指定的硬盘分区状态;-S:输出信息的单位。

参数

  • 事件间隔:状态信息刷新的时间间隔;
  • 次数:显示报告的次数。

实例

vmstat 3procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------ r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 0  0    320  42188 167332 1534368    0    0     4     7    1    0  0  0 99  0  0 0  0    320  42188 167332 1534392    0    0     0     0 1002   39  0  0 100  0  0 0  0    320  42188 167336 1534392    0    0     0    19 1002   44  0  0 100  0  0 0  0    320  42188 167336 1534392    0    0     0     0 1002   41  0  0 100  0  0 0  0    320  42188 167336 1534392    0    0     0     0 1002   41  0  0 100  0  0

字段说明:

Procs(进程)

  • r: 运行队列中进程数量,这个值也可以判断是否需要增加CPU。(长期大于1)
  • b: 等待IO的进程数量。

Memory(内存)

  • swpd: 使用虚拟内存大小,如果swpd的值不为0,但是SI,SO的值长期为0,这种情况不会影响系统性能。
  • free: 空闲物理内存大小。
  • buff: 用作缓冲的内存大小。
  • cache: 用作缓存的内存大小,如果cache的值大的时候,说明cache处的文件数多,如果频繁访问到的文件都能被cache处,那么磁盘的读IO bi会非常小。

Swap

  • si: 每秒从交换区写到内存的大小,由磁盘调入内存。
  • so: 每秒写入交换区的内存大小,由内存调入磁盘。

注意:内存够用的时候,这2个值都是0,如果这2个值长期大于0时,系统性能会受到影响,磁盘IO和CPU资源都会被消耗。有些朋友看到空闲内存(free)很少的或接近于0时,就认为内存不够用了,不能光看这一点,还要结合si和so,如果free很少,但是si和so也很少(大多时候是0),那么不用担心,系统性能这时不会受到影响的。

IO(现在的Linux版本块的大小为1kb)

  • bi: 每秒读取的块数
  • bo: 每秒写入的块数

注意:随机磁盘读写的时候,这2个值越大(如超出1024k),能看到CPU在IO等待的值也会越大。

system(系统)

  • in: 每秒中断数,包括时钟中断。
  • cs: 每秒上下文切换数。

注意:上面2个值越大,会看到由内核消耗的CPU时间会越大。

CPU(以百分比表示)

  • us: 用户进程执行时间百分比(user time)

us的值比较高时,说明用户进程消耗的CPU时间多,但是如果长期超50%的使用,那么我们就该考虑优化程序算法或者进行加速。

  • sy: 内核系统进程执行时间百分比(system time)

sy的值高时,说明系统内核消耗的CPU资源多,这并不是良性表现,我们应该检查原因。

  • wa: IO等待时间百分比

wa的值高时,说明IO等待比较严重,这可能由于磁盘大量作随机访问造成,也有可能磁盘出现瓶颈(块操作)。

  • id: 空闲时间百分比
9bbc174bb6bf856c9eae550143992731.png

top 查看进程活动状态以及一些系统状况

vmstat 查看系统状态、硬件和系统信息等

iostat 查看CPU 负载,硬盘状况

sar 综合工具,查看系统状况

mpstat 查看多处理器状况

netstat 查看网络状况

iptraf 实时网络状况监测

tcpdump 抓取网络数据包,详细分析

tcptrace 数据包分析工具

netperf 网络带宽工具

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: memcpy是一个常用的内存复制函数,它的性能对于系统的性能有着重要的影响。为了提升memcpy函数的性能,我们可以采取以下几种优化措施。 第一,通过使用SIMD指令集进行优化。SIMD指令集可以同时处理多个数据元素,从而提高数据复制的速度。一些常见的SIMD指令集如SSE(Streaming SIMD Extensions)和AVX(Advanced Vector Extensions)。使用SIMD指令集需要将数据按照指令集的要求进行对齐,以获得最佳的性能提升。 第二,使用软件指令级并行优化。将memcpy函数的复制操作拆分成多个并行任务,可以通过优化算法和数据结构来最大程度地利用处理器的并行性能。例如,可以将复制操作分成多个子任务,每个子任务复制一部分数据,然后使用多线程或者并行计算框架进行并行处理。 第三,使用缓存优化。在进行大量数据复制时,利用处理器的缓存可以显著提高性能。一种常见的优化方法是将大块数据分成适当大小的块,并按照一定的顺序进行复制,以最大限度地减少缓存失效。此外,还可以使用特定的数据结构,如缓存对齐数据结构,以提高数据复制的效率。 第四,使用硬件加速。一些现代处理器提供了硬件加速的功能,可以通过特定的指令来加速数据复制。例如,Intel的QuickPath Interconnect(QPI)和Advanced Micro Devices的HyperTransport技术可以提供高速数据传输,进一步提升memcpy函数的性能。 综上所述,通过使用SIMD指令集、软件指令级并行优化、缓存优化和硬件加速等方法,可以有效地提升memcpy函数的性能。但是需要注意的是,优化memcpy函数时应该综合考虑数据规模、处理器架构等因素,并进行适当的测试和评估,以确保优化结果的有效性。 ### 回答2: memcpy是一个用于内存复制的函数,其作用是将一段连续的内存块从源地址复制到目标地址。在性能提升优化方面,可以考虑以下几个方面: 1. 使用SIMD指令集:SIMD (Single Instruction, Multiple Data)指令集是一种并行计算方式,可以在同一时钟周期内对多个数据进行相同的操作。在适用的硬件平台上,可以使用SIMD指令集进行优化,提高memcpy函数的复制速度。 2. 内存对齐:对于一些体积较大的数据块,可以考虑使用内存对齐的方式进行复制。内存对齐是指保证数据块的起始地址是某个固定值的整数倍,这样可以利用硬件平台的高效复制机制,提高memcpy函数的执行效率。 3. 分段复制:对于大内存块的复制,可以将其分成多个小内存块进行复制。这样可以充分利用CPU的缓存机制,减少内存访问的开销。 4. 多线程:对于多核CPU,可以考虑使用多线程并行复制的方式。将大内存块分成多个小块,每个线程负责复制其中的一部分,可以提高数据复制的速度。 5. 使用专门优化的库函数:除了使用标准库的memcpy函数,还可以考虑使用一些专门优化的库函数,比如Intel的MKL库、GCC的优化内存复制函数等。 在实际应用中,根据具体的场景和平台选择合适的优化方法。通过对memcpy函数进行性能提升优化,可以加快数据复制的速度,提高程序的整体性能。 ### 回答3: memcpy函数是C语言中常用的一个内存拷贝函数,它能够将指定数量的字节从源内存块复制到目标内存块中。然而,在某些情况下,对memcpy函数的性能提升的优化是非常必要的。 首先,在处理大量数据时,普通的memcpy函数可能会导致性能瓶颈。为了提升性能,可以采用一些优化技巧。一种常见的优化方式是利用SIMD(单指令多数据)指令集,如SSE(流式SIMD扩展)或AVX(高级矢量扩展)。这些指令集能够一次性处理多个字节或数据,从而提高内存拷贝的速度。 其次,内存对齐也是提升memcpy性能的重要因素。对齐的内存访问通常比非对齐的内存访问更高效。因此,在使用memcpy时,可以尽量保证源和目标内存块的地址是对齐的。如果数据是非对齐的,可以使用一些特殊的内存拷贝函数,如memcpy_s或_mm_loadu_si128。 另外,使用多线程或并行处理也是提升memcpy性能的有效方法。可以将大块的内存拷贝任务拆分成多个子任务,并由多个线程同时进行处理。这样可以充分利用多核处理器的性能,加快内存拷贝的速度。 此外,还可以根据具体的应用场景来进行一些特定的优化。例如,可以根据内存块的大小选择最合适的内存拷贝函数,利用缓存预取和预读取技术来提前加载数据等。 综上所述,对于memcpy函数的性能提升和优化,可以通过使用SIMD指令集、内存对齐、多线程或并行处理以及其他特定的优化技巧来实现。这些优化方法可以在处理大量数据时提高内存拷贝的效率,从而提升整体性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值