lkml.org 
[lkml]   [1998]   [Sep]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectInteresting scheduling times
      Hi, all. I've been playing around with measuring Linux context
    switch times, and I noticed something curious: a Pentium/MMX 200 is
    doing much better than a PPro 180. Furthermore, a PPro 180 isn't doing
    heaps better than a Pentium 100.

    CPU process switch thread switch Kernel version
    Pentium 100 12 12 2.1.109
    PPro 180 8 4 2.1.122-pre2
    Pentium/MMX 200 4 2 2.1.104

    all times in microseconds for UP machines.

    Do these times seem a little odd to people?
    FYI: I've appended my testcode.

    Regards,

    Richard....
    ===============================================================================
    /* time-schedule.c

    Programme to test how long a context switch takes.

    Copyright (C) 1998 Richard Gooch

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Richard Gooch may be reached by email at rgooch@atnf.csiro.au
    The postal address is:
    Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
    */

    /*
    This programme will determine the context switch (scheduling) overhead on
    a system. It takes into account SMP machines. True context switches are
    measured.


    Written by Richard Gooch 15-SEP-1998

    Last updated by Richard Gooch 16-SEP-1998


    */
    #include <unistd.h>
    #ifndef _REENTRANT
    # define _REENTRANT
    #endif
    #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
    # define _POSIX_THREAD_SAFE_FUNCTIONS
    #endif
    #include <pthread.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
    #include <sched.h>
    #include <sys/time.h>
    #include <sys/mman.h>

    #if 0 /* Set to 1 if you don't have Karma */
    # define mt_num_processors() 1 /* Set to the number of processors */
    # define ERRSTRING sys_errlist[errno]
    # define FALSE 0
    # define TRUE 1
    #else
    # include <karma.h>
    # include <karma_mt.h>
    #endif


    #define MAX_ITERATIONS 10000

    static void hog_other_cpus ();
    static void run_yielder (int use_threads);
    static void *yielder_main (void *arg);
    static void s_term_handler ();
    static void run_low_priority (unsigned int num);


    static volatile unsigned int sched_count = 0;


    int main (int argc, char **argv)
    {
    int use_threads = FALSE;
    unsigned int count;
    signed long total_diffs;
    /*signed long diffs[MAX_ITERATIONS];*/
    static char *usage = "time-schedule [-h] [-thread] [num_running]";

    for (count = 1; count < argc; ++count)
    {
    if (strcmp (argv[count], "-h") == 0)
    {
    fprintf (stderr, "Usage:\t%s\n", usage);
    exit (0);
    }
    else if (strcmp (argv[count], "-thread") == 0) use_threads = TRUE;
    else run_low_priority ( atoi (argv[count]) );
    }
    if (geteuid () == 0)
    {
    struct sched_param sp;

    memset (&sp, 0, sizeof sp);
    sp.sched_priority = 10;
    if (sched_setscheduler (0, SCHED_FIFO, &sp) != 0)
    {
    fprintf (stderr, "Error changing to RT class\t%s\n", ERRSTRING);
    exit (1);
    }
    if (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)
    {
    fprintf (stderr, "Error locking pages\t%s\n", ERRSTRING);
    exit (1);
    }
    }
    else fprintf (stderr, "Not running with RT priority\n");
    hog_other_cpus ();
    run_yielder (use_threads);
    /*memset (diffs, 0, sizeof diffs);*/
    total_diffs = 0;
    for (count = 0; count < MAX_ITERATIONS; ++count)
    {
    int i;
    signed long diff;
    struct timeval before, after;

    gettimeofday (&before, NULL);
    for (i = 0; i < 10; ++i) sched_yield ();
    gettimeofday (&after, NULL);
    diff = 1000000 * (after.tv_sec - before.tv_sec);
    diff += after.tv_usec - before.tv_usec;
    diff = diff / 20;
    /*diffs[count] = diff;*/
    total_diffs += diff;
    }
    #if 0
    for (count = 0; count < MAX_ITERATIONS; count += 500)
    {
    printf ("%-8ld us\n", diffs[count]);
    }
    #endif
    printf ("Average scheduling latency: %ld us\n",
    total_diffs / MAX_ITERATIONS);
    fflush (stdout);
    if (use_threads) fprintf (stderr, "Number of yields: %u\n", sched_count);
    /* Finish up */
    kill (0, SIGTERM);
    return (0);
    } /* End Function main */


    static void hog_other_cpus ()
    /* [SUMMARY] Hog other CPUs with a high-priority job.
    [RETURNS] Nothing.
    */
    {
    unsigned int count;

    for (count = mt_num_processors (); count > 1; --count)
    {
    switch ( fork () )
    {
    case 0:
    /* Child */
    while (TRUE);
    break;
    case -1:
    /* Error */
    fprintf (stderr, "Error forking\t%s\n", ERRSTRING);
    kill (0, SIGTERM);
    break;
    default:
    /* Parent */
    break;
    }
    }
    fprintf (stderr, "Started %u hog processes\n", mt_num_processors () - 1);
    } /* End Function hog_other_cpus */

    static void run_yielder (int use_threads)
    /* [SUMMARY] Run other process which will continuously yield.
    <use_threads> If TRUE, the yielding process is just a thread.
    [RETURNS] Nothing.
    */
    {
    struct sigaction new_action;
    pthread_t thread;

    if (use_threads)
    {
    if (pthread_create (&thread, NULL, yielder_main, NULL) != 0)
    {
    fprintf (stderr, "Error creating thread\t%s\n", ERRSTRING);
    kill (0, SIGTERM);
    }
    fprintf (stderr, "Started yielder thread\n");
    return;
    }
    switch ( fork () )
    {
    case 0:
    /* Child */
    break;
    case -1:
    /* Error */
    fprintf (stderr, "Error forking\t%s\n", ERRSTRING);
    kill (0, SIGTERM);
    break;
    default:
    /* Parent */
    fprintf (stderr, "Started yielder process\n");
    return;
    /*break;*/
    }
    memset (&new_action, 0, sizeof new_action);
    sigemptyset (&new_action.sa_mask);
    new_action.sa_handler = s_term_handler;
    if (sigaction (SIGTERM, &new_action, NULL) != 0)
    {
    fprintf (stderr, "Error setting SIGTERM handler\t%s\n", ERRSTRING);
    exit (1);
    }
    yielder_main (NULL);
    } /* End Function run_yielder */

    static void *yielder_main (void *arg)
    /* [SUMMARY] Yielder function.
    <arg> An arbitrary argument. Ignored.
    [RETURNS] NULL.
    */
    {
    while (TRUE)
    {
    sched_yield ();
    ++sched_count;
    }
    } /* End Function yielder_main */

    static void s_term_handler ()
    {
    fprintf (stderr, "Number of yields: %u\n", sched_count);
    exit (0);
    } /* End Function s_term_handler */

    static void run_low_priority (unsigned int num)
    /* [SUMMARY] Run low priority processes.
    <num> Number of processes.
    [RETURNS] Nothing.
    */
    {
    fprintf (stderr, "Starting %u low priority processes\n", num);
    for (; num > 0; --num)
    {
    switch ( fork () )
    {
    case 0:
    /* Child */
    if (nice (10) != 0)
    {
    fprintf (stderr, "Error nicing\t%s\n", ERRSTRING);
    kill (0, SIGTERM);
    }
    while (TRUE) sched_yield ();
    break;
    case -1:
    /* Error */
    fprintf (stderr, "Error forking\t%s\n", ERRSTRING);
    kill (0, SIGTERM);
    break;
    default:
    /* Parent */
    break;
    }
    }
    } /* End Function run_low_priority */

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:44    [W:0.031 / U:0.736 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site