home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.os.linux
- Path: sparky!uunet!mcsun!news.funet.fi!hydra!klaava!torvalds
- From: torvalds@klaava.Helsinki.FI (Linus Torvalds)
- Subject: Re: A simple xload program using proc fs
- Message-ID: <1993Jan12.175521.3537@klaava.Helsinki.FI>
- Keywords: xload
- Organization: University of Helsinki
- References: <1993Jan12.125403.14817@olymp.informatik.uni-bonn.de>
- Date: Tue, 12 Jan 1993 17:55:21 GMT
- Lines: 81
-
- This isn't really a comment on the xload program, but just a general
- warning about performance, as I've seen a couple of mails/postings
- saying that the /proc thing is slower than a kmem based 'ps' etc.
-
- While the /proc interface may not be the fastest possible, you can
- probably get much better perfomance by readin things in bigger chunks
- and only once. I wrote the routines in such a way that they should work
- fine even if you do several small reads, but the whole buffer is always
- calculated for each read, so using stdio routines is generally not the
- best way to handle it (at the very least, stdio needs to do two reads:
- the second one will just return EOF).
-
- In the xload case this isn't really something you need to care about, as
- the buffer is both small and fast to calculate, and xload doesn't need
- to read it very often anyway, but this is also an easy way to show the
- "preferred" way of handling the /proc directory, so I'll use it as an
- example.
-
- In article <1993Jan12.125403.14817@olymp.informatik.uni-bonn.de> lederer@informatik.uni-bonn.de writes:
- >
- >void get_value(Widget w, XtPointer client_data, XtPointer chart_value)
- >{
- > FILE *loadavg;
- >
- > if( (loadavg=fopen(LOADAVG,"r"))==NULL)
- > {
- > fprintf(stderr,"couldn't open %s",LOADAVG);
- > exit(1);
- > }
- > fscanf(loadavg,"%lf", (double *) chart_value);
- > fclose(loadavg);
- >}
-
- The optimal way to do this is probably:
-
- void get_value(Widget w, XtPointer client_data, XtPointer chart_value)
- {
- static int fd = -1;
- static char buf[4097];
- int i;
-
- *(double *) chart_value = 0.0;
- if (fd < 0) {
- fd = open(LOADAVG,O_RDONLY);
- if (fd < 0) {
- fprintf(stderr,"couldn't open %s\n",LOADAVG);
- exit(1);
- }
- }
- i = read(fd,buf,4096);
- if (i > 0) {
- buf[i] = '\0';
- sscanf(buf,"%lf", (double *) chart_value);
- }
- }
-
- A couple of points:
-
- - do the open only once if at all possible, as you'll otherwise have to
- look up the name every time. If you have to open several different
- /proc files, and not much else, the fastest way is to do a "chdir()"
- to the /proc directory, and then use relative filenames. This way
- you avoid looking up the inodes etc from disk, and can do name lookup
- entirely in the procfs (this probably only pays off with 'ps', and
- maybe not even there..).
-
- - read all the statistics files (/proc/loadavg, /proc/meminfo,
- /proc/<pid>/stat etc) with just one read, with a buffer of 4096
- bytes. Also note that the strings are usually not '\0'-terminated,
- so you have to do that yourself with the value returned by the read
- if you are going to use them as strings. This means that the buffer
- actually has to be 1 byte longer than a page for safety (but note the
- special meaning of '\0' in /proc/xxx/environ and /proc/xxx/cmdline)
-
- - these points are meaningless unless you really care about
- performance: all the /proc files have been designed so that you can
- use shell scripts, perl or whatever to read and parse them. So use
- perl/shell scripts (or stdio) when appropriate, and try to optimize
- only when there is any reason for it.
-
- Linus
-