mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
sperf.c
C Source File · 183 lines
sperf.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <time.h>
// Feel free to change the data structures generated by AI.
#define MAX_SYSCALLS 1024
#define TOP_N 5
extern char **environ;
typedef struct {
char name[64];
double time;
} syscall_stat;
typedef struct {
syscall_stat stats[MAX_SYSCALLS];
int count;
double total_time;
} syscall_stats;
int parse_strace_line(char *line, char *syscall_name, double *time) {
if (!('a' <= line[0] && line[0] <= 'z')) return -1;
int n = strlen(line);
int flag1 = 0, flag2 = 0, flag3 = 0;
int name_ptr = 0;
*time = 0;
double base = 1.0;
for (int i = 0; i < n; i++) {
if (!flag1) syscall_name[name_ptr++] = line[i];
if (i != n - 1 && !flag1 && line[i + 1] == '(') flag1 = 1;
if (line[i] == '<') flag2 = 1;
else if (flag2 && line[i] == '>') flag2 = 0;
else if (flag2) {
if (line[i] == '.') flag3 = 1;
else if (!flag3) {
*time = (*time) * 10 + (line[i] - '0');
}else {
base /= 10;
*time += base * (line[i] - '0');
}
}
}
syscall_name[name_ptr] = '\0';
return 0;
}
void add_syscall(syscall_stats *stats, const char *name, double time) {
(*stats).total_time += time;
int n = (*stats).count;
for (int i = 0; i < n; i++) {
if (strcmp((*stats).stats[i].name, name) == 0) {
(*stats).stats[i].time += time;
return;
}
}
int _len = strlen(name);
memcpy((*stats).stats[n].name, name, sizeof(char) * (_len + 1));
(*stats).stats[n].time = time;
(*stats).count++;
}
void swap(syscall_stat *a, syscall_stat *b) {
syscall_stat c = *a;
*a = *b;
*b = c;
}
void print_top_syscalls(syscall_stats *stats, int k) {
int n = (*stats).count;
while (1) {
int flag = 0;
for (int i = 0; i + 1 < n; i++) {
if ((*stats).stats[i].time < (*stats).stats[i + 1].time) {
swap(((*stats).stats + i), ((*stats).stats + i + 1));
flag = 1;
}
}
if (!flag) break;
}
k = k > n ? n : k;
for (int i = 0; i < k; i++) {
printf("%s (%d%%)\n", (*stats).stats[i].name, (int)((*stats).stats[i].time / (*stats).total_time * 100.0));
}
for (int i = 0; i < 80; i++) {
fputc('\0', stdout);
}
fflush(stdout);
}
char buffer[1 << 16];
int buffer_ptr;
syscall_stats ss;
int handle_buffer() {
int pos = 0, retval = 0;
for (int i = 0; i < buffer_ptr; i++) {
if (buffer[i] == '\n') {
int len = i - pos + 1;
char *line = (char *)malloc(sizeof(char) * (len + 1));
memcpy(line, buffer + pos, sizeof(char) * len);
line[len] = '\0';
char *syscall_name = (char *)malloc(sizeof(char) * 64);
double time;
int ret = parse_strace_line(line, syscall_name, &time);
pos = i + 1;
if (ret == -1) {
retval = -1;
free(line); free(syscall_name);
continue;
}
add_syscall(&ss, syscall_name, time);
free(line); free(syscall_name);
}
}
int _buffer_ptr = buffer_ptr - pos;
for (int i = 0; i < _buffer_ptr; i++) {
buffer[i] = buffer[pos++];
}
buffer_ptr = _buffer_ptr; buffer[buffer_ptr] = '\0';
return retval;
}
int main(int argc, char *argv[]) {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe error\n");
return 1;
}
int pid = fork();
if (pid == 0) { //child
close(pipefd[0]);
dup2(pipefd[1], STDERR_FILENO);
close(pipefd[1]);
char ** my_argv = (char**)malloc(sizeof (char*) * (argc + 2));
my_argv[0] = "strace";
my_argv[1] = "-T";
for (int i = 1; i < argc; i++) {
my_argv[i + 1] = argv[i];
}
my_argv[argc + 1] = NULL;
execve("/bin/strace", my_argv, environ);
} else { //parent
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
struct pollfd fds[2];
fds[0].fd = STDIN_FILENO; fds[0].events = POLLIN | POLLHUP;
int timeout = 100000;
while (1) {
struct timeval now, _now;
gettimeofday(&now, NULL);
int r = poll(fds, 1, timeout / 1000 + 5);
gettimeofday(&_now, NULL);
int dif = (_now.tv_sec - now.tv_sec) * 1000000 + (_now.tv_usec - now.tv_usec);
timeout -= dif;
if (r > 0) {
if (fds[0].revents & POLLIN) {
int len;
if ((len = read(STDIN_FILENO, buffer + buffer_ptr, sizeof(buffer) - buffer_ptr)) > 0) buffer_ptr += len;
handle_buffer();
}
if (fds[0].revents & POLLHUP) {
while (read(STDIN_FILENO, buffer, sizeof(buffer)) > 0);
break;
}
}
if (r == 0 || timeout < 0) {
print_top_syscalls(&ss, 5);
timeout = 100000;
}
if (r < 0) break;
}
}
return 0;
}

目录