Skip to content

Instantly share code, notes, and snippets.

@vi
Created November 29, 2011 16:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vi/1405425 to your computer and use it in GitHub Desktop.
Save vi/1405425 to your computer and use it in GitHub Desktop.
Simple process IO read/write rate limiter based on strace
From 7959a97980894e1a47361e566d234a5f341dd05d Mon Sep 17 00:00:00 2001
From: Vitaly _Vi Shukela <vi0oss@gmail.com>
Date: Tue, 29 Nov 2011 19:29:50 +0300
Subject: [PATCH] Strace-based speed limiter
Apply to strace-4.6
Set env SPEEDLIMIT_READ=1000 and slow down other process with strace
Example: SPEEDLIMIT_READ=$((200*1024)) ./strace -o /dev/null -p `pidof wget`
---
strace.c | 11 +++++++++++
syscall.c | 29 +++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/strace.c b/strace.c
index 774d172..1ffb63b 100644
--- a/strace.c
+++ b/strace.c
@@ -199,6 +199,10 @@ usage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
" /* this is broken, so don't document it
-z -- print only succeeding syscalls\n\
*/
+"Set SPEEDLIMIT_READ or SPEEDLIMIT_WRITE environment variables to\n\
+ bytes per seconds to slow down I/O of the traced process by\n\
+ sleeping after each successfull read/write-like syscall.\n\
+"
, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
exit(exitval);
}
@@ -914,6 +918,13 @@ main(int argc, char *argv[])
}
}
+ extern int speedlimit_read;
+ extern int speedlimit_write;
+ speedlimit_read=0;
+ speedlimit_write=0;
+ if(getenv("SPEEDLIMIT_READ")) sscanf(getenv("SPEEDLIMIT_READ"), "%i", &speedlimit_read);
+ if(getenv("SPEEDLIMIT_WRITE")) sscanf(getenv("SPEEDLIMIT_WRITE"), "%i", &speedlimit_write);
+
if ((optind == argc) == !pflag_seen)
usage(stderr, 1);
diff --git a/syscall.c b/syscall.c
index e66ac0a..7c2b369 100644
--- a/syscall.c
+++ b/syscall.c
@@ -168,6 +168,9 @@ static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
const char *const *errnoent;
int nerrnos;
+int speedlimit_read;
+int speedlimit_write;
+
int current_personality;
#ifndef PERSONALITY0_WORDSIZE
@@ -2556,6 +2559,32 @@ trace_syscall_exiting(struct tcb *tcp)
}
printtrailer();
+ if (sysent[tcp->scno].sys_func == sys_read ||
+ sysent[tcp->scno].sys_func == sys_pread ||
+ sysent[tcp->scno].sys_func == sys_pread64 ||
+ sysent[tcp->scno].sys_func == sys_recv ||
+ sysent[tcp->scno].sys_func == sys_recvfrom ||
+ sysent[tcp->scno].sys_func == sys_readv) {
+
+ long long int ret = tcp->u_rval;
+ if (ret > 0 && speedlimit_read>0) {
+ usleep(ret * 1000000 / speedlimit_read);
+ }
+ } else
+ if (sysent[tcp->scno].sys_func == sys_write ||
+ sysent[tcp->scno].sys_func == sys_pwrite ||
+ sysent[tcp->scno].sys_func == sys_pwrite64 ||
+ sysent[tcp->scno].sys_func == sys_send ||
+ sysent[tcp->scno].sys_func == sys_sendto ||
+ sysent[tcp->scno].sys_func == sys_writev) {
+
+ long long int ret = tcp->u_rval;
+ if (ret > 0 && speedlimit_write>0) {
+ usleep(ret * 1000000 / speedlimit_write);
+ }
+ }
+
+
dumpio(tcp);
if (fflush(tcp->outf) == EOF)
return -1;
--
1.7.6.4
@vi
Copy link
Author

vi commented Nov 29, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment