Re: Kernel increase.

Linus Torvalds (Linus.Torvalds@cs.Helsinki.FI)
Wed, 6 Sep 1995 07:25:53 +0300


root: "Re: Kernel increase." (Sep 5, 11:11):
> > I think it's just that kernel profiling is on by default in the newer
> > 1.3.x kernels: I guess I should tun it off again as I haven't been using
> > it for a while..
>
> hmm, tryed to use it a couple of days ago (first time ever), as it was
> on, and i'd forgotten to turn it off, ran readprofile, and it fell over
> with something like readprofile: /proc/profile: unexpected eof,
> readprofile is version 1.1, this a known problem (ie that readprofile's
> too old, get a newer one), or new ?

Ehh.. I have a hacked up version of a kprof that was originally written
by ramon@ie3.clubs.etsit.upm.es, but I changed it around quite a bit.
This version shows percent time used etc, and sorts the list in
ascending order.

Hmm.. I haven't used this in a while. Does it still work? The code
isn't pretty, but it's short. Somebody should probably clean it up some
more..

Linus

---------- kprof.c ----------
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <linux/autoconf.h>

#define BUFSIZE 1024

struct entry {
struct entry * next;
unsigned long time;
unsigned long address;
char name[1];
};

struct entry * list = NULL;

void do_symbol(int time, unsigned long address, char * name)
{
struct entry * entry = malloc(sizeof(struct entry) + strlen(name));
struct entry ** tmp;

entry->time = time;
entry->address = address;
strcpy(entry->name, name + (*name == '_'));
tmp = &list;
while (*tmp) {
if ((*tmp)->time > entry->time)
break;
tmp = &(*tmp)->next;
}
entry->next = *tmp;
*tmp = entry;
}

void show_symbols(unsigned long total)
{
struct entry * entry = list;

while (entry) {
printf("%10u %5d.%02d%% %08x %s\n" ,
entry->time,
(entry->time*10000/total) / 100,
(entry->time*10000/total) % 100,
entry->address, entry->name);
entry = entry->next;
}
}

int main(void)
{
int fp;
FILE *kmap;
int current_symbol_value , next_symbol_value;
char current_symbol[80] , next_symbol[80];
int has_read , total = 0, j;

fp = open("/proc/profile", O_RDONLY);
if (fp < 0) {
perror("/proc/profile");
exit(1);
}
kmap = fopen("/System.map","r");
if (!kmap) {
kmap = fopen("/usr/src/linux/System.map","r");
if (!kmap) {
perror("System.map");
exit(1);
}
}
fscanf(kmap , "%x %*s %s\n" , &current_symbol_value , current_symbol );
fscanf(kmap , "%x %*s %s\n" , &next_symbol_value , next_symbol );
lseek (fp , sizeof(unsigned int) , SEEK_SET);
/* For old kernels.. */
/* lseek (fp , (current_symbol_value-1)*sizeof(unsigned int) >> CONFIG_PROFILE_SHIFT , SEEK_CUR); */

for (;;) {
unsigned int buffer[(next_symbol_value - current_symbol_value) >> CONFIG_PROFILE_SHIFT];
unsigned int this_time = 0;

if (next_symbol_value == current_symbol_value) {
strcpy(current_symbol, next_symbol);
fscanf(kmap, "%x %*s %s\n", &next_symbol_value, next_symbol);
continue;
}
has_read = read (fp , buffer , sizeof(buffer) );
for ( j = 0 ; j < has_read/sizeof(unsigned int) ; j++)
this_time += buffer[j];
if (this_time != 0) {
do_symbol(this_time, current_symbol_value, current_symbol);
total += this_time;
}
if (has_read < (next_symbol_value -current_symbol_value)
>> CONFIG_PROFILE_SHIFT * sizeof(unsigned long) ||
next_symbol_value == current_symbol_value )
break;
strcpy ( current_symbol , next_symbol );
current_symbol_value = next_symbol_value;
fscanf(kmap , "%x %*s %s\n" , &next_symbol_value , next_symbol );
}
do_symbol(total, 0, "total");
show_symbols(total);
return(0);
}
----------