---
title: 减少内存拷贝
description: "基于数据流分析，发现并减少内存拷贝次数，能降低CPU使用率，并减少内存带宽占用。"
url: https://www.hikunpeng.com/document/detail/zh/perftuning/tuningtip/kunpengtuning_12_0049.html
sourcePath: /source/zh/perftuning/tuningtip/kunpengtuning_12_0049.html
indexId: a979bf4ace9598ebefc26661f490324c20ba3310894bdbc1896e27d8c7cf4dc158
---
# 减少内存拷贝

#### 原理

基于数据流分析，发现并减少内存拷贝次数，能降低CPU使用率，并减少内存带宽占用。


#### 修改方式

减少内存拷贝要基于业务逻辑进行分析，本文列举几种减少内存拷贝的实现机制：

- 样例一：使用sendfile代替send/sendto/write等函数将文件发送给对端。
如下两条语句将文件发送给对端，一般会有4次内存拷贝：
```
ssize_t read (int fd, void *buf, size_t count);
ssize_t send (int s, const void * buf, size_t len, int flags);
```


  - read函数一般有2次内存拷贝：DMA将数据传输到内核的PageCache；内核将数据传输到应用态的buf。
  - send函数一般有2次内存拷贝：write函数将应用态的buf的拷贝到内核；DMA将数据搬运到网卡。
    使用如下函数实现只需要两次内存拷贝：

    1 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

    内核通过DMA将文件搬运到缓存（一次内存拷贝），然后把缓存的描述信息（位置和长度）传递给TCP/IP协议栈，内核再通过DMA将缓存搬运到网卡（第二次内存拷贝）。

    除了修改代码，部分开源软件已经支持这个特性，如Nginx可以通过sendfile on参数打开这个功能。

- 样例二：进程间通信使用共享内存代替socket/pipe通信。
  内存共享方式可以让多个进程操作同样的内存区域，相比socket通信的方式，内存拷贝少。应用程序可以使用shmget等函数实现进程间通信。
