lkml.org 
[lkml]   [1996]   [Apr]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Tracing memory->memory copies in linux...
> 
> Does anyone have trace information on what fraction of the time
> linux spends performing memory->memory copies, how big these copies are,
> etc? Or a pointer to what I need to know to get the information myself?

Depending on what you do, the kernel may spend about 20% of the time in just a
loop that clears a page - you can get some statistics with the kernel profiler
code (I'm including my current silly profiling code as an attachement: enable
the code with a kernel command line of "profile=2" at the LILO prompt for any
reasonably new kernel).

Note that most of the stuff is inlined, so you may see "do_no_page()" using up
lots of time, for example. That's not because do_no_page is inefficient (it
isn't), but simply because it ends up zeroing out the new bss pages it gives to
processes, and that takes time.. (my silly profile program has some capability
to do a instruction-by-instruction profile, but you need to compile in the
function name for the function you want to profile and then look at the profile
by hand (using gdb's "disassemble" to see the kernel code side by side with the
instruction profile).

The profil.c file is based on somebody else's code, sorry for the lack of
attributions. I've fixed it to sort the output and do some other things better,
and it's almost usable if you know exactly what you're doing. You may need to
read the source code to know exactly what it does, though.

Oh, if you want to reset the profiling info, just do a "echo > /proc/profile",
then run the particular mix of programs you want to profile the kernel on, and
then run the profile.c program to parse the information..

Linus#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <linux/autoconf.h>

#define prof_func "verify_area"

#define BUFSIZE 1024

#ifndef CONFIG_PROFILE_SHIFT
#define CONFIG_PROFILE_SHIFT 2
#endif

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;
}
}

/* If you do not speak Spanish:
* valor_simbolo_actual: current_symbol_value
* valor_simbolo_siguiente: next_symbol_value
* simbolo_actual: current_symbol
* next_symbol: next_symbol
* leidos: read (past participle)
* total: total
*/

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 );
puts(prof_func);

for (;;) {
unsigned int buffer[(next_symbol_value - current_symbol_value) >> CONFIG_PROFILE_SHIFT];
unsigned int tiempo = 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;
}
lseek (fp , sizeof(unsigned int)+current_symbol_value-0x100000 , SEEK_SET);
has_read = read (fp , buffer , sizeof(buffer) );
for ( j = 0 ; j < has_read/sizeof(unsigned int) ; j++) {
if (!strcmp(prof_func, current_symbol))
printf("%08x %d\n", j*4+current_symbol_value, buffer[j]);
tiempo += buffer[j];
}
if (tiempo != 0) {
do_symbol(tiempo, current_symbol_value, current_symbol);
total += tiempo;
}
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);
}
\
 
 \ /
  Last update: 2005-03-22 13:37    [W:0.043 / U:0.900 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site