$ gcc -o main main.c
$ ./main
splice with discard took about 0.12762 seconds
splice with full discard took about 0.15904 seconds
normal splice took about 0.02920 seconds
sendfile from memfd took about 0.15539 seconds
Last active
October 24, 2017 19:33
-
-
Save Mic92/c25ed7c331f6db927b246465420a55d7 to your computer and use it in GitHub Desktop.
Splice vs memfd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <unistd.h> | |
#include <sys/syscall.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <stdint.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <sys/sendfile.h> | |
#include <sys/syscall.h> | |
#include <stdlib.h> | |
# ifndef __NR_memfd_create | |
# if defined __x86_64__ | |
# define __NR_memfd_create 319 | |
# elif defined __arm__ | |
# define __NR_memfd_create 385 | |
# elif defined __aarch64__ | |
# define __NR_memfd_create 279 | |
# elif defined __s390__ | |
# define __NR_memfd_create 350 | |
# elif defined _MIPS_SIM | |
# if _MIPS_SIM == _MIPS_SIM_ABI32 | |
# define __NR_memfd_create 4354 | |
# endif | |
# if _MIPS_SIM == _MIPS_SIM_NABI32 | |
# define __NR_memfd_create 6318 | |
# endif | |
# if _MIPS_SIM == _MIPS_SIM_ABI64 | |
# define __NR_memfd_create 5314 | |
# endif | |
# elif defined __i386__ | |
# define __NR_memfd_create 356 | |
# elif defined __arc__ | |
# define __NR_memfd_create 279 | |
# else | |
# warning "__NR_memfd_create unknown for your architecture" | |
# endif | |
# endif | |
static inline int memfd_create(const char *name, unsigned int flags) { | |
# ifdef __NR_memfd_create | |
return syscall(__NR_memfd_create, name, flags); | |
# else | |
errno = ENOSYS; | |
return -1; | |
# endif | |
} | |
struct fuse_out_header { | |
uint32_t len; | |
int32_t error; | |
uint64_t unique; | |
}; | |
struct fuse_write_out { | |
uint32_t size; | |
uint32_t padding; | |
}; | |
int main() { | |
int pipefd[2], pipefd2[2]; | |
pipe(&pipefd[0]); | |
pipe(&pipefd2[0]); | |
int fd = open("/run/user/1000/a", O_CREAT|O_TRUNC|O_RDWR, 0755); | |
const int size = 1024 * 4; | |
ftruncate(fd, size); | |
fcntl(pipefd[0], F_SETPIPE_SZ, size + 4096); | |
fcntl(pipefd2[0], F_SETPIPE_SZ, size + 4096); | |
struct timespec tstart={0,0}, tend={0,0}; | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
uint8_t buf[sizeof(struct fuse_out_header) + sizeof(struct fuse_write_out)]; | |
loff_t offset = 0; | |
for (int i = 0; i < 99999; i++) { | |
offset = 0; | |
splice(fd, &offset, pipefd[1], NULL, size, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
write(pipefd2[1], buf, sizeof(buf)); | |
read(pipefd[0], buf, sizeof(buf)); | |
splice(pipefd[0], NULL, pipefd2[1], NULL, size - sizeof(buf), SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
offset = 0; | |
splice(pipefd2[0], NULL, fd, &offset, size, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
} | |
clock_gettime(CLOCK_MONOTONIC, &tend); | |
printf("splice with discard took about %.5f seconds\n", | |
((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - | |
((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)); | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
uint8_t *buf2 = (uint8_t*)malloc(size); | |
for (int i = 0; i < 99999; i++) { | |
offset = 0; | |
splice(fd, &offset, pipefd[1], NULL, size, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
read(pipefd[0], buf2, size); | |
write(fd, buf2, size); | |
} | |
free(buf2); | |
clock_gettime(CLOCK_MONOTONIC, &tend); | |
printf("splice with full discard took about %.5f seconds\n", | |
((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - | |
((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)); | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
for (int i = 0; i < 99999; i++) { | |
splice(fd, NULL, pipefd[1], NULL, size, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
splice(pipefd[0], NULL, fd, NULL, size, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); | |
} | |
clock_gettime(CLOCK_MONOTONIC, &tend); | |
printf("normal splice took about %.5f seconds\n", | |
((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - | |
((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)); | |
close(pipefd[0]); | |
close(pipefd[1]); | |
int tmpfd = memfd_create("test", 0); | |
clock_gettime(CLOCK_MONOTONIC, &tstart); | |
for (int i = 0; i < 99999; i++) { | |
loff_t offset = 0; | |
sendfile(fd, tmpfd, &offset, size); | |
lseek(tmpfd, 0, SEEK_SET); | |
sendfile(tmpfd, fd, &offset, size); | |
lseek(fd, 0, SEEK_SET); | |
} | |
clock_gettime(CLOCK_MONOTONIC, &tend); | |
printf("sendfile from memfd took about %.5f seconds\n", | |
((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - | |
((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment