Skip to content

Instantly share code, notes, and snippets.

@Mic92
Last active October 24, 2017 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mic92/c25ed7c331f6db927b246465420a55d7 to your computer and use it in GitHub Desktop.
Save Mic92/c25ed7c331f6db927b246465420a55d7 to your computer and use it in GitHub Desktop.
Splice vs memfd
$ 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
#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