我使用mmap,读写系统调用复制文件。我想看看mmap速度的优势。
我考虑了四种复制方法:
但是,结果是,无论块大小如何,mmap总是比读和写慢。
源代码:
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
constexpr long MAP_SIZE = 1L*1024*1024*1024;
constexpr int BLOCK_SIZE = 256;
using namespace std;
void test1(int fd1, int fd2){
// read+write
char buf[BLOCK_SIZE];
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
clock_t t1 = clock();
for(long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++){
// use for fair
off_t file_offset = i*BLOCK_SIZE;
off_t page_align_offset = i*BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE)-1);
off_t in_page_offset = file_offset-page_align_offset;
int mm_len = in_page_offset+BLOCK_SIZE;
read(fd1, buf, BLOCK_SIZE);
write(fd2, buf, BLOCK_SIZE);
}
clock_t t2 = clock();
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "read+write use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
}
void test2(int fd1, int fd2){
// mmap+write
char *buf;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
clock_t t1 = clock();
for(long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++){
off_t file_offset = i*BLOCK_SIZE;
off_t page_align_offset = i*BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE)-1);
off_t in_page_offset = file_offset - page_align_offset;
int mm_len = in_page_offset + BLOCK_SIZE;
buf = (char *)mmap(NULL, mm_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, page_align_offset);
write(fd2, buf+in_page_offset, BLOCK_SIZE);
munmap(buf, mm_len);
}
clock_t t2 = clock();
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap+write use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
}
void test3(int fd1, int fd2){
// read+mmap
char buf1[BLOCK_SIZE];
char* buf2;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
clock_t t1 = clock();
for(long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++){
off_t file_offset = i*BLOCK_SIZE;
off_t page_align_offset = i*BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE)-1);
off_t in_page_offset = file_offset-page_align_offset;
int mm_len = in_page_offset+BLOCK_SIZE;
read(fd1, buf1, BLOCK_SIZE);
buf2 = (char *)mmap(NULL, mm_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, page_align_offset);
memcpy(buf2+in_page_offset, buf1, BLOCK_SIZE);
munmap(buf2, mm_len);
}
clock_t t2 = clock();
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "read+mmap use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
}
void test4(int fd1, int fd2){
// mmap+mmap
char* buf1;
char* buf2;
clock_t t1 = clock();
for(long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++){
off_t file_offset = i*BLOCK_SIZE;
off_t page_align_offset = i*BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE)-1);
off_t in_page_offset = file_offset-page_align_offset;
int mm_len = in_page_offset+BLOCK_SIZE;
buf1 = (char *)mmap(NULL, mm_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, page_align_offset);
buf2 = (char *)mmap(NULL, mm_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, page_align_offset);
memcpy(buf2+in_page_offset, buf1+in_page_offset, BLOCK_SIZE);
munmap(buf1, mm_len);
munmap(buf2, mm_len);
}
clock_t t2 = clock();
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap+mmap use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
}
int main(int argc, char *argv[])
{
int fd1, fd2;
fd1 = shm_open("shm1", O_RDWR|O_CREAT, 0644);
fd2 = shm_open("shm2", O_RDWR|O_CREAT, 0644);
// fd1 = open("f1", O_RDWR|O_CREAT, 0644);
// fd2 = open("f2", O_RDWR|O_CREAT, 0644);
if(fd1 < 0 || fd2 < 0){
printf("shm_open failed\n");
exit(1);
}
if (ftruncate(fd1, MAP_SIZE) < 0){
printf("ftruncate failed\n");
exit(1);
}
if (ftruncate(fd2, MAP_SIZE) < 0){
printf("ftruncate failed\n");
exit(1);
}
test1(fd1, fd2);
test2(fd1, fd2);
test3(fd1, fd2);
test4(fd1, fd2);
}其中一个结果显示mmap速度较慢:
total size is: 1073741824
block size is: 4096
read+write use 254.571ms
total size is: 1073741824
block size is: 4096
mmap+write use 486.342ms
total size is: 1073741824
block size is: 4096
read+mmap use 537.277ms
total size is: 1073741824
block size is: 4096
mmap+mmap use 737.734ms发布于 2021-04-21 18:45:50
clock函数测量进程使用的CPU时间。它对工作是在流程上下文中完成还是在内核上下文中完成非常敏感。
当线程从一个文件中读取一些数据时,无论是通过调用read还是访问mmap,在读取操作完成之前,该线程就不能取得进一步的进展。最有效的方法是立即完成与该操作相关的所有CPU工作,以便进程能够重新开始工作。由于您测量了在这种情况下完成了多少工作,因此,如果以最有效的方式完成更多的工作,则实际上会对更有效的操作进行惩罚。
所以这种测量实际上是对低效率的奖励。在流程上下文之外完成的工作不被计算在内,因此该方法效率低下的工作越多(同时使流程等待时间更长),所用的时间就越少。
我认为主要的问题是你没有一个明确的问题。为什么测量“速度”意味着测量使用的进程CPU时间?为什么不测量墙壁时间呢?
发布于 2021-04-25 02:10:01
辅助实验test567
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
constexpr long MAP_SIZE = 1L * 1024 * 1024;
constexpr int BLOCK_SIZE = 4;
using namespace std;
void test1(int fd1, int fd2)
{
// read+write
char buf[BLOCK_SIZE];
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
// use for fair
off_t file_offset = i * BLOCK_SIZE;
off_t page_align_offset = i * BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE) - 1);
off_t in_page_offset = file_offset - page_align_offset;
int mm_len = in_page_offset + BLOCK_SIZE;
read(fd1, buf, BLOCK_SIZE);
write(fd2, buf, BLOCK_SIZE);
}
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "read+write use "
// << (t2 - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "read+write use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test2(int fd1, int fd2)
{
// mmap+write
char *buf;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
off_t file_offset = i * BLOCK_SIZE;
off_t page_align_offset = i * BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE) - 1);
off_t in_page_offset = file_offset - page_align_offset;
int mm_len = in_page_offset + BLOCK_SIZE;
buf = (char *)mmap(NULL, mm_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, page_align_offset);
write(fd2, buf + in_page_offset, BLOCK_SIZE);
munmap(buf, mm_len);
}
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "mmap+write use "
// << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap+write use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test3(int fd1, int fd2)
{
// read+mmap
char buf1[BLOCK_SIZE];
char *buf2;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
off_t file_offset = i * BLOCK_SIZE;
off_t page_align_offset = i * BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE) - 1);
off_t in_page_offset = file_offset - page_align_offset;
int mm_len = in_page_offset + BLOCK_SIZE;
read(fd1, buf1, BLOCK_SIZE);
buf2 = (char *)mmap(NULL, mm_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, page_align_offset);
memcpy(buf2 + in_page_offset, buf1, BLOCK_SIZE);
munmap(buf2, mm_len);
}
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "read+mmap use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000
// << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "read+mmap use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test4(int fd1, int fd2)
{
// mmap+mmap
char *buf1;
char *buf2;
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
off_t file_offset = i * BLOCK_SIZE;
off_t page_align_offset = i * BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE) - 1);
off_t in_page_offset = file_offset - page_align_offset;
int mm_len = in_page_offset + BLOCK_SIZE;
buf1 = (char *)mmap(NULL, mm_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, page_align_offset);
buf2 = (char *)mmap(NULL, mm_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, page_align_offset);
memcpy(buf2 + in_page_offset, buf1 + in_page_offset, BLOCK_SIZE);
munmap(buf1, mm_len);
munmap(buf2, mm_len);
}
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "mmap+mmap use "
// << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000
// << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap+mmap use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test5(int fd1, int fd2)
{
// mmap(large)+write
char *buf;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
// for(long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++){
// off_t file_offset = i*BLOCK_SIZE;
// off_t page_align_offset = i*BLOCK_SIZE & ~(sysconf(_SC_PAGE_SIZE)-1);
// off_t in_page_offset = file_offset - page_align_offset;
// int mm_len = in_page_offset + BLOCK_SIZE;
// buf = (char *)mmap(NULL, mm_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, page_align_offset);
// write(fd2, buf+in_page_offset, BLOCK_SIZE);
// munmap(buf, mm_len);
// }
buf = (char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
write(fd2, buf + i * BLOCK_SIZE, BLOCK_SIZE);
}
munmap(buf, MAP_SIZE);
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "mmap+write use "
// << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000
// << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap(large)+write use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test6(int fd1, int fd2)
{
// read+mmap(large)
char buf1[BLOCK_SIZE];
char *buf2;
lseek(fd1, 0, SEEK_SET);
lseek(fd2, 0, SEEK_SET);
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
buf2 = (char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
read(fd1, buf2 + i * BLOCK_SIZE, BLOCK_SIZE);
}
munmap(buf2, MAP_SIZE);
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "read+mmap use " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "read+mmap(large) use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
void test7(int fd1, int fd2)
{
// mmap(large)+mmap(large)
char *buf1;
char *buf2;
timeval tv1;
gettimeofday(&tv1, nullptr);
// clock_t t1 = clock();
buf1 = (char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
buf2 = (char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
for (long i = 0; i < MAP_SIZE / BLOCK_SIZE; i++)
{
memcpy(buf2 + i * BLOCK_SIZE, buf1 + i * BLOCK_SIZE, BLOCK_SIZE);
}
munmap(buf1, MAP_SIZE);
munmap(buf2, MAP_SIZE);
// clock_t t2 = clock();
// cout << "total size is: " << MAP_SIZE << endl;
// cout << "block size is: " << BLOCK_SIZE << endl;
// cout << "mmap+mmap use "
// << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms" << endl;
timeval tv2;
gettimeofday(&tv2, nullptr);
cout << "total size is: " << MAP_SIZE << endl;
cout << "block size is: " << BLOCK_SIZE << endl;
cout << "mmap(large)+mmap(large) use "
<< (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000.0
<< "ms" << endl;
}
int main(int argc, char *argv[])
{
int fd1, fd2;
fd1 = shm_open("shm1", O_RDWR | O_CREAT, 0644);
fd2 = shm_open("shm2", O_RDWR | O_CREAT, 0644);
// fd1 = open("f1", O_RDWR|O_CREAT, 0644);
// fd2 = open("f2", O_RDWR|O_CREAT, 0644);
if (fd1 < 0 || fd2 < 0)
{
printf("shm_open failed\n");
exit(1);
}
if (ftruncate(fd1, MAP_SIZE) < 0)
{
printf("ftruncate failed\n");
exit(1);
}
if (ftruncate(fd2, MAP_SIZE) < 0)
{
printf("ftruncate failed\n");
exit(1);
}
test1(fd1, fd2);
test2(fd1, fd2);
test3(fd1, fd2);
test4(fd1, fd2);
test5(fd1, fd2);
test6(fd1, fd2);
test7(fd1, fd2);
}
total size is: 1048576
block size is: 4
read+write use 113.286ms
total size is: 1048576
block size is: 4
mmap+write use 353.928ms
total size is: 1048576
block size is: 4
read+mmap use 355.605ms
total size is: 1048576
block size is: 4
mmap+mmap use 602.21ms
total size is: 1048576
block size is: 4
mmap(large)+write use 57.245ms
total size is: 1048576
block size is: 4
read+mmap(large) use 43.094ms
total size is: 1048576
block size is: 4
mmap(large)+mmap(large) use 0.611mshttps://stackoverflow.com/questions/67071882
复制相似问题