Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/nsprpub/pr/tests/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  perf.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "nspr.h"
#include "plgetopt.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int _debug_on = 0;
#define DPRINTF(arg) \
  if (_debug_on) printf arg

#include "obsolete/prsem.h"

PRLock* lock;
PRMonitor* mon;
PRMonitor* mon2;

#define DEFAULT_COUNT 1000

PRInt32 count;

static void nop(int a, int b, int c) {}

static void LocalProcedureCall(void) {
  PRInt32 i;

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

static void DLLProcedureCall(void) {
  PRInt32 i;
  PRThreadState state;
  PRThread* self = PR_GetCurrentThread();

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

static void Now(void) {
  PRInt32 i;
  PRTime time;

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

static void Interval(void) {
  PRInt32 i;
  PRIntervalTime time;

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

static void IdleLock(void) {
  PRInt32 i;

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

static void IdleMonitor(void) {
  PRInt32 i;

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

static void IdleCMonitor(void) {
  PRInt32 i;

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

/************************************************************************/

static void PR_CALLBACK dull(void* arg) {}

static void CDThread(void) {
  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);
  }
}

static int alive;
static int cxq;

static void PR_CALLBACK CXReader(void* arg) {
  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()));
}

static void PR_CALLBACK CXWriter(void* arg) {
  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()));
}

static void ContextSwitch(PRThreadScope scope1, PRThreadScope scope2) {
  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);
}

static void ContextSwitchUU(void) {
  ContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
}

static void ContextSwitchUK(void) {
  ContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
}

static void ContextSwitchKU(void) {
  ContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
}

static void ContextSwitchKK(void) {
  ContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
}

/************************************************************************/

static void PR_CALLBACK SemaThread(void* argSema) {
  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()));
}

static PRSemaphore* sem_set1[2];
static PRSemaphore* sem_set2[2];

static void SemaContextSwitch(PRThreadScope scope1, PRThreadScope scope2) {
  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]);
}

static void SemaContextSwitchUU(void) {
  SemaContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
}

static void SemaContextSwitchUK(void) {
  SemaContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
}

static void SemaContextSwitchKU(void) {
  SemaContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
}

static void SemaContextSwitchKK(void) {
  SemaContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
}

/************************************************************************/

static void Measure(void (*func)(void), const char* msg) {
  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);
}

int main(int argc, char** argv) {
  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();

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

Messung V0.5
C=89 H=91 G=89

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.