LQ Newbie
Registered: May 2007
Posts: 1
Rep:
|
How to get the cpu perfomance using the native library
Hi,
I am working in an profiling tool. Where we need to profile the j2ee Applications. For win32 I am able to create the .dll file to get the parrameters like CPU Utilixation, process id and memory usage.
But when I was using the tool in linux, all parameter value is zero. I was trying to create the .so file for linux. I am new to linux, I got one solaris C file for getting the cpu info, memory info, can U please help me to convert the solaris specific calls of that C file to Linux specific suystem calls.
Below is the C file I am suign whidh is for Solaris...
===============================================================
/* ------------------------------------------------------------------------- */
/*
* Solaris-dependent system routines and kernel calls
* Used for getting memory and CPU consumption statistics
*
* Author: Peter V. Mikhalenko (C) 2004, Deutsche Bank [peter@mikhalenko.ru]
*/
/* ------------------------------------------------------------------------- */
#include <kvm.h>
# ifndef KSTAT_DATA_UINT32
# define ui32 ul
# endif
#include
#include
#include
#include
#include
#include
#include
#include
#define _STRUCTURED_PROC 1
#include
#define prpsinfo psinfo
#define pr_fill pr_nlwp
/* These require an ANSI C compiler "Reisser cpp" doesn't like this */
#define pr_state pr_lwp.pr_state
#define pr_oldpri pr_lwp.pr_oldpri
#define pr_nice pr_lwp.pr_nice
#define pr_pri pr_lwp.pr_pri
#define pr_onpro pr_lwp.pr_onpro
#define ZOMBIE(p) ((p)->pr_nlwp == 0)
#define SIZE_K(p) ((p)->pr_size)
#define RSS_K(p) ((p)->pr_rssize)
#define PROCFS "/proc"
/* definitions for indices in the nlist array */
#define X_V 0
#define X_MPID 1
#define X_ANONINFO 2
#define X_MAXMEM 3
#define X_SWAPFS_MINFREE 4
#define X_FREEMEM 5
#define X_AVAILRMEM 6
#define X_AVENRUN 7
#define X_CPU 8
#define X_NPROC 9
#define X_NCPUS 10
static struct nlist nlst[] =
{
{"v"}, /* 0 */ /* replaced by dynamic allocation */
{"mpid"}, /* 1 */
#if OSREV >= 56
/* this structure really has some extra fields, but the first three match */
{"k_anoninfo"}, /* 2 */
#else
{"anoninfo"}, /* 2 */
#endif
{"maxmem"}, /* 3 */ /* use sysconf */
{"swapfs_minfree"}, /* 4 */ /* used only w/ USE_ANONINFO */
{"freemem"}, /* 5 */ /* available from kstat >= 2.5 */
{"availrmem"}, /* 6 */ /* available from kstat >= 2.5 */
{"avenrun"}, /* 7 */ /* available from kstat */
{"cpu"}, /* 8 */ /* available from kstat */
{"nproc"}, /* 9 */ /* available from kstat */
{"ncpus"}, /* 10 */ /* available from kstat */
{0}
};
static kstat_ctl_t *kc = NULL;
static kstat_t **cpu_ks;
static cpu_stat_t *cpu_stat;
static int ncpus;
kvm_t *kd;
static unsigned long freemem_offset;
static unsigned long maxmem_offset;
static unsigned long freemem = -1L;
static unsigned long maxmem = -1L;
/* pagetok function is really a pointer to an appropriate function */
static int pageshift;
static int (*p_pagetok) ();
#define pagetok(size) ((*p_pagetok)(size))
int pagetok_none(int size) {
return(size);
}
int pagetok_left(int size) {
return(size << pageshift);
}
int pagetok_right(int size) {
return(size >> pageshift);
}
#define UPDKCID(nk,ok) \
if (nk == -1) { \
perror("kstat_read "); \
exit(1); \
} \
if (nk != ok)\
goto kcid_changed;
void initKVM() {
int i;
/* perform the kvm_open - suppress error here */
kd = kvm_open (NULL, NULL, NULL, O_RDONLY, NULL);
/* calculate pageshift value */
i = sysconf(_SC_PAGESIZE);
pageshift = 0;
while ((i >>= 1) > 0)
{
pageshift++;
}
/* calculate an amount to shift to K values */
/* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
pageshift -= 10;
/* now determine which pageshift function is appropriate for the
result (have to because x << y is undefined for y < 0) */
if (pageshift > 0)
{
/* this is the most likely */
p_pagetok = pagetok_left;
}
else if (pageshift == 0)
{
p_pagetok = pagetok_none;
}
else
{
p_pagetok = pagetok_right;
pageshift = -pageshift;
}
}
#define SI_LEN 512
#define BUFSIZE 256
char * sol_getSysInfo() {
char * retbuf = (char*)malloc(SI_LEN);
int curend = 0;
int maxl = SI_LEN;
*retbuf=0;
char * buf = (char*)malloc(BUFSIZE);
long res = sysinfo(SI_SYSNAME,buf,BUFSIZE);
if (res>0 && res<=maxl) {
strcat(retbuf,buf);
curend=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curend0 && res<=maxl) {
strcat(retbuf,buf);
curend+=res-1;
maxl=SI_LEN-curend;
}
if (curendvalue.ui32 > ncpus) {
ncpus = kn->value.ui32;
cpu_ks = (kstat_t **) realloc (cpu_ks, ncpus * sizeof (kstat_t *));
cpu_stat = (cpu_stat_t *) realloc (cpu_stat,
ncpus * sizeof (cpu_stat_t));
}
for (ks = kc->kc_chain; ks;
ks = ks->ks_next)
{
if (strncmp(ks->ks_name, "cpu_stat", 8) == 0)
{
nkcid = kstat_read(kc, ks, NULL);
/* if kcid changed, pointer might be invalid */
UPDKCID(nkcid, kcid);
cpu_ks[ncpu] = ks;
ncpu++;
if (ncpu > ncpus)
{
fprintf(stderr, "kstat finds too many cpus: should be %d\n",
ncpus);
exit(1);
}
}
}
/* note that ncpu could be less than ncpus, but that's okay */
changed = 0;
}
/* return the number of cpus found */
ncpus=ncpu;
return ncpu;
}
unsigned long sol_getMaxMem() {
maxmem = pagetok(sysconf(_SC_PHYS_PAGES));
return maxmem;
}
unsigned long sol_getFreeMem() {
kstat_t *ks;
kstat_named_t *kn;
ks = kstat_lookup(kc, "unix", 0, "system_pages");
if (kstat_read(kc, ks, 0) == -1) {
perror("kstat_read");
exit(1);
}
if (kd != NULL) { /* always get freemem from kvm if we can*/
(void) getkval (freemem_offset, (int *) (&freemem), sizeof (freemem), "freemem");
} else {
kn = kstat_data_lookup(ks, "freemem");
if (kn)
freemem = kn->value.ul;
}
return (unsigned long)pagetok(freemem);
}
// Returns the number of milliseconds (not nanoseconds and seconds) elapsed on processor
// since process start. The returned value is adjusted for the number of processors in the system.
long int sol_getProcessCPUTime(int pid,int nproc) {
struct prpsinfo currproc;
int fd;
char buf[30];
long int retval=0;
snprintf(buf, sizeof(buf), "%s/%d/psinfo", PROCFS, pid);
if ((fd = open (buf, O_RDONLY)) < 0) {
return 0L;
}
if (read(fd, &currproc, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
(void)close(fd);
return 0L;
}
(void)close(fd);
retval = (currproc.pr_time.tv_sec * 1000 + currproc.pr_time.tv_nsec / 1000000) / nproc;
return retval;
}
// Returns percentage CPU by pid
// In Solaris 8 it is contained in procfs
double sol_getProcessCPUPercentage(int pid) {
struct prpsinfo currproc;
int fd;
char buf[30];
double retval=0.0;
snprintf(buf, sizeof(buf), "%s/%d/psinfo", PROCFS, pid);
if ((fd = open (buf, O_RDONLY)) < 0) {
return 0;
}
if (read(fd, &currproc, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
(void)close(fd);
return 0;
}
(void)close(fd);
retval = ((double)currproc.pr_pctcpu)/0x8000*100;
return retval;
}
// Returns current space allocated for the process, in bytes. Those pages may or may not be in memory.
long sol_getMemoryUsage(int pid) {
struct prpsinfo currproc;
int fd;
char buf[30];
double retval=0.0;
snprintf(buf, sizeof(buf), "%s/%d/psinfo", PROCFS, pid);
if ((fd = open (buf, O_RDONLY)) < 0) {
return 0;
}
if (read(fd, &currproc, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
(void)close(fd);
return 0;
}
(void)close(fd);
retval = currproc.pr_size;
return retval;
}
// Returns current process space being resident in memory.
long sol_getMemoryResident(int pid) {
struct prpsinfo currproc;
int fd;
char buf[30];
double retval=0.0;
snprintf(buf, sizeof(buf), "%s/%d/psinfo", PROCFS, pid);
if ((fd = open (buf, O_RDONLY)) < 0) {
return 0;
}
if (read(fd, &currproc, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
(void)close(fd);
return 0;
}
(void)close(fd);
retval = currproc.pr_rssize;
return retval;
}
/*
* getkval(offset, ptr, size, refstr) - get a value out of the kernel.
* "offset" is the byte offset into the kernel for the desired value,
* "ptr" points to a buffer into which the value is retrieved,
* "size" is the size of the buffer (and the object to retrieve),
* "refstr" is a reference string used when printing error meessages,
* if "refstr" starts with a '!', then a failure on read will not
* be fatal (this may seem like a silly way to do things, but I
* really didn't want the overhead of another argument).
*
*/
int getkval (unsigned long offset,
int *ptr,
int size,
char *refstr)
{
if (kvm_read (kd, offset, (char *) ptr, size) != size)
{
if (*refstr == '!')
{
return (0);
}
else
{
fprintf (stderr, "top: kvm_read for %s: %s\n", refstr, strerror(errno));
exit(23);
}
}
return (1);
}
===============================================================
|