Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
perf.c File Reference
#include "nspr.h"
#include "plgetopt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "obsolete/prsem.h"

Go to the source code of this file.

Defines

#define DPRINTF(arg)   if (_debug_on) printf arg
#define DEFAULT_COUNT   1000

Functions

static void nop (int a, int b, int c)
static void LocalProcedureCall (void)
static void DLLProcedureCall (void)
static void Now (void)
static void Interval (void)
static void IdleLock (void)
static void IdleMonitor (void)
static void IdleCMonitor (void)
static void PR_CALLBACK dull (void *arg)
static void CDThread (void)
static void PR_CALLBACK CXReader (void *arg)
static void PR_CALLBACK CXWriter (void *arg)
static void ContextSwitch (PRThreadScope scope1, PRThreadScope scope2)
static void ContextSwitchUU (void)
static void ContextSwitchUK (void)
static void ContextSwitchKU (void)
static void ContextSwitchKK (void)
static void PR_CALLBACK SemaThread (void *argSema)
static void SemaContextSwitch (PRThreadScope scope1, PRThreadScope scope2)
static void SemaContextSwitchUU (void)
static void SemaContextSwitchUK (void)
static void SemaContextSwitchKU (void)
static void SemaContextSwitchKK (void)
static void Measure (void(*func)(void), const char *msg)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

int _debug_on = 0
PRLocklock
PRMonitormon
PRMonitormon2
PRInt32 count
static int alive
static int cxq
static PRSemaphoresem_set1 [2]
static PRSemaphoresem_set2 [2]

Define Documentation

#define DEFAULT_COUNT   1000

Definition at line 61 of file perf.c.

Definition at line 46 of file perf.c.


Function Documentation

static void CDThread ( void  ) [static]

Definition at line 145 of file perf.c.

{
    PRInt32 i;
    int num_threads = count;

    /*
     * Cannot create too many threads
     */
    if (num_threads > 1000)
    num_threads = 1000;

    for (i = 0; i < num_threads; i++) {
        PRThread *t = PR_CreateThread(PR_USER_THREAD,
                      dull, 0, 
                      PR_PRIORITY_NORMAL,
                      PR_LOCAL_THREAD,
                      PR_UNJOINABLE_THREAD,
                      0);
        if (NULL == t) {
            fprintf(stderr, "CDThread: cannot create thread %3d\n", i);
        } else {
            DPRINTF(("CDThread: created thread %3d \n",i));
        }
        PR_Sleep(0);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ContextSwitch ( PRThreadScope  scope1,
PRThreadScope  scope2 
) [static]

Definition at line 223 of file perf.c.

{
    PRThread *t1, *t2;

    PR_EnterMonitor(mon2);
    alive = 2;
    cxq = 0;

    t1 = PR_CreateThread(PR_USER_THREAD,
                      CXReader, 0, 
                      PR_PRIORITY_NORMAL,
                      scope1,
                      PR_UNJOINABLE_THREAD,
                      0);
    if (NULL == t1) {
        fprintf(stderr, "ContextSwitch: cannot create thread\n");
    } else {
        DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",
                (scope1 == PR_GLOBAL_THREAD ?
                "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
                            t1));
    }
    t2 = PR_CreateThread(PR_USER_THREAD,
                      CXWriter, 0, 
                      PR_PRIORITY_NORMAL,
                      scope2,
                      PR_UNJOINABLE_THREAD,
                      0);
    if (NULL == t2) {
        fprintf(stderr, "ContextSwitch: cannot create thread\n");
    } else {
        DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",
                (scope2 == PR_GLOBAL_THREAD ?
                "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
                            t2));
    }

    /* Wait for both of the threads to exit */
    while (alive) {
    PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
    }
    PR_ExitMonitor(mon2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ContextSwitchKK ( void  ) [static]

Definition at line 282 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void ContextSwitchKU ( void  ) [static]

Definition at line 277 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void ContextSwitchUK ( void  ) [static]

Definition at line 272 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void ContextSwitchUU ( void  ) [static]

Definition at line 267 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK CXReader ( void arg) [static]

Definition at line 175 of file perf.c.

{
    PRInt32 i, n;

    PR_EnterMonitor(mon);
    n = count / 2;
    for (i = 0; i < n; i++) {
    while (cxq == 0) {
            DPRINTF(("CXReader: thread = 0x%lx waiting\n",
                    PR_GetCurrentThread()));
        PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    }
    --cxq;
    PR_Notify(mon);
    }
    PR_ExitMonitor(mon);

    PR_EnterMonitor(mon2);
    --alive;
    PR_Notify(mon2);
    PR_ExitMonitor(mon2);
    DPRINTF(("CXReader: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK CXWriter ( void arg) [static]

Definition at line 199 of file perf.c.

{
    PRInt32 i, n;

    PR_EnterMonitor(mon);
    n = count / 2;
    for (i = 0; i < n; i++) {
    while (cxq == 1) {
            DPRINTF(("CXWriter: thread = 0x%lx waiting\n",
                    PR_GetCurrentThread()));
        PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    }
    ++cxq;
    PR_Notify(mon);
    }
    PR_ExitMonitor(mon);

    PR_EnterMonitor(mon2);
    --alive;
    PR_Notify(mon2);
    PR_ExitMonitor(mon2);
    DPRINTF(("CXWriter: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void DLLProcedureCall ( void  ) [static]

Definition at line 78 of file perf.c.

{
    PRInt32 i;
       PRThreadState state;
       PRThread *self = PR_CurrentThread();

    for (i = 0; i < count; i++) {
       state = PR_GetThreadState(self);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK dull ( void arg) [static]

Definition at line 141 of file perf.c.

{
}

Here is the caller graph for this function:

static void IdleCMonitor ( void  ) [static]

Definition at line 129 of file perf.c.

{
    PRInt32 i;

    for (i = 0; i < count; i++) {
    PR_CEnterMonitor((void*)7);
    PR_CExitMonitor((void*)7);
    }
}

Here is the caller graph for this function:

static void IdleLock ( void  ) [static]

Definition at line 109 of file perf.c.

{
    PRInt32 i;

    for (i = 0; i < count; i++) {
    PR_Lock(lock);
    PR_Unlock(lock);
    }
}

Here is the caller graph for this function:

static void IdleMonitor ( void  ) [static]

Definition at line 119 of file perf.c.

{
    PRInt32 i;

    for (i = 0; i < count; i++) {
    PR_EnterMonitor(mon);
    PR_ExitMonitor(mon);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void Interval ( void  ) [static]

Definition at line 99 of file perf.c.

{
    PRInt32 i;
    PRIntervalTime time;

    for (i = 0; i < count; i++) {
        time = PR_IntervalNow();
    }
}

Here is the caller graph for this function:

static void LocalProcedureCall ( void  ) [static]

Definition at line 69 of file perf.c.

{
    PRInt32 i;

    for (i = 0; i < count; i++) {
    nop(i, i, 5);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 403 of file perf.c.

{
       PLOptStatus os;
       PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
       while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    {
              if (PL_OPT_BAD == os) continue;
        switch (opt->option)
        {
        case 'd':  /* debug mode */
                     _debug_on = 1;
            break;
        case 'c':  /* loop count */
            count = atoi(opt->value);
            break;
         default:
            break;
        }
    }
       PL_DestroyOptState(opt);

    if (0 == count) count = DEFAULT_COUNT;
    
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
       PR_BlockClockInterrupts();
       PR_UnblockClockInterrupts();
    PR_STDIO_INIT();

#ifdef XP_MAC
    SetupMacPrintfLog("perf.log");
#endif

    lock = PR_NewLock();
    mon = PR_NewMonitor();
    mon2 = PR_NewMonitor();

    Measure(LocalProcedureCall, "local procedure call overhead");
    Measure(DLLProcedureCall, "DLL procedure call overhead");
    Measure(Now, "current calendar time");
    Measure(Interval, "interval time");
    Measure(IdleLock, "idle lock lock/unlock pair");
    Measure(IdleMonitor, "idle monitor entry/exit pair");
    Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
    Measure(CDThread, "create/destroy thread pair");
    Measure(ContextSwitchUU, "context switch - user/user");
    Measure(ContextSwitchUK, "context switch - user/kernel");
    Measure(ContextSwitchKU, "context switch - kernel/user");
    Measure(ContextSwitchKK, "context switch - kernel/kernel");
    Measure(SemaContextSwitchUU, "sema context switch - user/user");
    Measure(SemaContextSwitchUK, "sema context switch - user/kernel");
    Measure(SemaContextSwitchKU, "sema context switch - kernel/user");
    Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel");

    printf("--------------\n");
    printf("Adding 7 additional CPUs\n");

    PR_SetConcurrency(8);
    printf("--------------\n");

    Measure(LocalProcedureCall, "local procedure call overhead");
    Measure(DLLProcedureCall, "DLL procedure call overhead");
    Measure(Now, "current calendar time");
    Measure(Interval, "interval time");
    Measure(IdleLock, "idle lock lock/unlock pair");
    Measure(IdleMonitor, "idle monitor entry/exit pair");
    Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
    Measure(CDThread, "create/destroy thread pair");
    Measure(ContextSwitchUU, "context switch - user/user");
    Measure(ContextSwitchUK, "context switch - user/kernel");
    Measure(ContextSwitchKU, "context switch - kernel/user");
    Measure(ContextSwitchKK, "context switch - kernel/kernel");
    Measure(SemaContextSwitchUU, "sema context switch - user/user");
    Measure(SemaContextSwitchUK, "sema context switch - user/kernel");
    Measure(SemaContextSwitchKU, "sema context switch - kernel/user");
    Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel");

    PR_DestroyLock(lock);
    PR_DestroyMonitor(mon);
    PR_DestroyMonitor(mon2);

    PR_Cleanup();
    return 0;
}

Here is the call graph for this function:

static void Measure ( void(*)(void func,
const char *  msg 
) [static]

Definition at line 390 of file perf.c.

{
    PRIntervalTime start, stop;
    double d;

    start = PR_IntervalNow();
    (*func)();
    stop = PR_IntervalNow() - start;
    d = (double)PR_IntervalToMicroseconds(stop);

    printf("%40s: %6.2f usec\n", msg, d / count);
}

Here is the caller graph for this function:

static void nop ( int  a,
int  b,
int  c 
) [static]

Definition at line 65 of file perf.c.

{
}

Here is the caller graph for this function:

static void Now ( void  ) [static]

Definition at line 89 of file perf.c.

{
    PRInt32 i;
    PRTime time;

    for (i = 0; i < count; i++) {
        time = PR_Now();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void SemaContextSwitch ( PRThreadScope  scope1,
PRThreadScope  scope2 
) [static]

Definition at line 314 of file perf.c.

{
    PRThread *t1, *t2;
    sem_set1[0] = PR_NewSem(1);
    sem_set1[1] = PR_NewSem(0);
    sem_set2[0] = sem_set1[1];
    sem_set2[1] = sem_set1[0];

    PR_EnterMonitor(mon2);
    alive = 2;
    cxq = 0;

    t1 = PR_CreateThread(PR_USER_THREAD,
                      SemaThread, 
                      sem_set1, 
                      PR_PRIORITY_NORMAL,
                      scope1,
                      PR_UNJOINABLE_THREAD,
                      0);
    if (NULL == t1) {
        fprintf(stderr, "SemaContextSwitch: cannot create thread\n");
    } else {
        DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",
                (scope1 == PR_GLOBAL_THREAD ?
                "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
                            t1));
    }
    t2 = PR_CreateThread(PR_USER_THREAD,
                      SemaThread, 
                      sem_set2, 
                      PR_PRIORITY_NORMAL,
                      scope2,
                      PR_UNJOINABLE_THREAD,
                      0);
    if (NULL == t2) {
        fprintf(stderr, "SemaContextSwitch: cannot create thread\n");
    } else {
        DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",
                (scope2 == PR_GLOBAL_THREAD ?
                "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
                            t2));
    }

    /* Wait for both of the threads to exit */
    while (alive) {
        PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
    }
    PR_ExitMonitor(mon2);

    PR_DestroySem(sem_set1[0]);
    PR_DestroySem(sem_set1[1]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void SemaContextSwitchKK ( void  ) [static]

Definition at line 382 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void SemaContextSwitchKU ( void  ) [static]

Definition at line 377 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void SemaContextSwitchUK ( void  ) [static]

Definition at line 372 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void SemaContextSwitchUU ( void  ) [static]

Definition at line 367 of file perf.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void PR_CALLBACK SemaThread ( void argSema) [static]

Definition at line 289 of file perf.c.

{
    PRSemaphore **sem = (PRSemaphore **)argSema;
    PRInt32 i, n;

    n = count / 2;
    for (i = 0; i < n; i++) {
        DPRINTF(("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n",
                PR_GetCurrentThread(), sem[0]));
        PR_WaitSem(sem[0]);
        DPRINTF(("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n",
                PR_GetCurrentThread(), sem[1]));
        PR_PostSem(sem[1]);
    }

    PR_EnterMonitor(mon2);
    --alive;
    PR_Notify(mon2);
    PR_ExitMonitor(mon2);
    DPRINTF(("SemaThread: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 45 of file perf.c.

int alive [static]

Definition at line 172 of file perf.c.

Definition at line 63 of file perf.c.

int cxq [static]

Definition at line 173 of file perf.c.

Definition at line 57 of file perf.c.

Definition at line 58 of file perf.c.

Definition at line 59 of file perf.c.

PRSemaphore* sem_set1[2] [static]

Definition at line 311 of file perf.c.

PRSemaphore* sem_set2[2] [static]

Definition at line 312 of file perf.c.