[Translation] C # data structures and algorithms-Chapter 1 (end) Time Test

Source: Internet
Author: User

Time Test

This book uses a practical method to analyze the data structures and algorithms to be studied. We prefer to use a simple benchmarking method instead of Big O analysis. This test tells us how many seconds (or other time units) it takes to run a code segment. Our benchmark test time test measures the time it takes to run an algorithm. Benchmarking is a science and art, and you must be careful when timing a piece of code to get a correct analysis result. Let's take a closer look.

A time test that is too simple

First, we need some code in time. To briefly describe the problem, we first output the content of an array to the console subroutine for timing. The following code is used:

Static void DisplayNums (int [] arr)

{

For (int I = 0; I <= arr. GetUpperBound (0); I ++)

Console. Write (arr [I] + "");

}

This array is initialized in another part of the program, which will be studied later. To time this sub-function, we need to create a variable and assign the system time when the sub-function is called to this variable. In addition, we need to store the time when a sub-function returns. The following describes how to implement these functions:

DateTime startTime;

TimeSpan endTime;

StartTime = DateTime. Now;

EndTime = DateTime. Now. Subtract (startTime );

Run this code on my laptop (1.4mHz Windows XP Professional Edition). This subroutine runs for about 5 seconds (4.9917 seconds ). Although it seems that this code is suitable for executing a time-consuming test, it is not enough to run the code in the computing. Net environment. Why?

First, this code tests the time consumed by the subfunction being called until the subfunction returns to the main program. The time occupied by other processes running with the C # program is also recorded in the time test results.

Second, the timing Code does not take into account the time for garbage collection in the. Net environment. In a running environment such as. Net, the system may pause at any time to perform garbage collection. This simple code does not take any action to acknowledge the existence of garbage collection and the timing result is easily affected by garbage collection. So how should we deal with this problem?

Time consumption test in. Net Environment

In the. Net environment, we need to consider the threads running our program and the fact that garbage collection may happen at any time. We need to take these factors into account when designing our timing code.

Let's take a look at how to control garbage collection. First, let's discuss the role of garbage collection. In C #, the memory space of reference types (such as strings, arrays, and instance objects of classes) is allocated in the space called heap. Heap is the memory space used to save data items (previously mentioned types. Value types, such as common variables, are stored on the stack. References to reference data are also stored on the stack, but the data actually stored in the reference type is stored in the stack.

Variables stored on the stack are released when the declared subroutine execution is complete. On the other hand, the variables stored on the managed stack remain in the heap until the garbage collection process is called. Heap data is removed only when there is no dynamic reference to it through garbage collection.

Garbage collection can occur at any time when the program is executed. However, we should do our best to ensure that the garbage collector does not run during our timing code execution. We can forcibly call the Garbage Collector to prevent arbitrary garbage collection .. . Net environment provides a special object-GC for calling garbage collection. Notify the system to perform garbage collection. Let's simply write:

GC. Collect ();

However, this is not all we have to do. Each object stored in the heap has a special method to become a Terminator. The Terminator method is executed in the last step before the object is deleted. The problem with Terminator methods is that they are not executed in a regular way. In fact, you cannot even determine whether an object's Terminator is running. However, we know that before we determine that an object is deleted, its terminator method will certainly run. To ensure this, we add a line of code to tell the program to wait for the final method of all objects on the stack to run before continuing to execute. This line of code is as follows:

GC. WaitForPendingFinalizers ();

We have removed one obstacle and only one to be resolved-use the appropriate thread. In the. Net environment, a program runs in a thread, also known as an application domain. This allows the operating system to separate different programs and run them simultaneously. In a process, a part of a program or program runs in a thread. The execution time of a program is allocated by the operating system through threads. When we time the Code of a program, we want to ensure that the time is only the time occupied by the code assigned to the program by the process, rather than the time when the operating system executes other tasks.

We can use the Process class in the. NET class library to implement this function. The Process method allows us to select the current Process (the Process in which our program is running), the thread in which the program is running, and a timer to store the start time of the thread. All these methods can be merged into one call, and the return value of this call function is the variable that stores the time (a TimeSpan object) when the thread starts to execute. The following is the code (two lines in total ).

TimeSpan startingTime;

StartingTime = Process. GetCurrentProcess (). Threads [0]

. UserProcessorTime;

For the rest, we only need to capture the time when the code segment we timing stops. The sample code is as follows:

Duration = Process. GetCurrentProcess (). Threads [0]. UserProcessorTime

. Subtract (startingTime );

Now, let's merge all of these into a program to test the same code we tested before.

Using System;

Using System. Diagnostics;

 

Class chapter1

{

Static void Main ()

{

Int [] nums = new int [100000];

BuildArray (nums );

TimeSpan startTime;

TimeSpan duration;

StartTime = Process. GetCurrentProcess (). Threads [0]. UserProcessorTime;

DisplayNums (nums );

Duration = Process. GetCurrentProcess (). Threads [0]. UserProcessorTime. Subtract (startTime );

Console. WriteLine ("Time:" + duration. TotalSeconds );

}

 

Static void BuildArray (int [] arr)

{

For (int I = 0; I <= 99999; I ++)

Arr [I] = I;

}

 

Static void DisplayNums (int [] arr)

{

For (int I = 0; I <= arr. GetUpperBound (0); I ++)

Console. Write (arr [I] + "");

}

}

The program returns 0.2526 with the new improved timing code. This is in great contrast to the result of nearly five seconds returned by the first timing code. Obviously, there is a big difference between the two timing technologies, so you should use a suitable. NET Technology for code timing in the. NET environment.

Timing Testing

Although we don't need a class to run our time test code, it makes sense to rewrite the code into a class, this is mainly because we can reduce the number of lines of code we test to keep our code clear.

A timing class requires the following data members:

StartingTime-Start Time for saving the code we are testing.

Duration-end time of the code we are testing

We chose to use the TimeSpan data type to store the startingtTime and duration data members who saved the time. We will use only one constructor and one default constructor to initialize the two data members to 0.

We need a method to notify a timer object when to start timing and when to stop. We also need a method to return the data stored in the duration data member.

As you can see, this Timing class is quite small and requires only a few methods, as defined below:

Public class Timing

{

TimeSpan startingTime;

TimeSpan duration;

Public Timing ()

{

StartingTime = new TimeSpan (0 );

Duration = new TimeSpan (0 );

}

Public void StopTime ()

{

Duration = Process. GetCurrentProcess (). Threads [0]

. UserProcessorTime. Subtract (startingTime );

}

Public void startTime ()

{

GC. Collect ();

GC. WaitForPendingFinalizers ();

StartingTime = Process. GetCurrentProcess (). Threads [0]

. UserProcessorTime;

}

Public TimeSpan Result ()

{

Return duration;

}

}

The following program uses the overwritten Timing class to test the DisplayNames subfunction.

Using System;

Using System. Diagnostics;

 

Public class Timing

{

TimeSpan startingTime;

TimeSpan duration;

Public Timing ()

{

StartingTime = new TimeSpan (0 );

Duration = new TimeSpan (0 );

}

Public void stopTime ()

{

Duration = Process. GetCurrentProcess (). Threads [0]. UserProcessorTime. Subtract (startingTime );

}

Public void startTime ()

{

GC. Collect ();

GC. WaitForPendingFinalizers ();

StartingTime = Process. GetCurrentProcess (). Threads [0]. UserProcessorTime;

}

Public TimeSpan Result ()

{

Return duration;

}

}

 

Class chapter1

{

Static void Main ()

{

Int [] nums = new int [100000];

BuildArray (nums );

Timing tObj = new Timing ();

TObj. startTime ();

DisplayNums (nums );

TObj. stopTime ();

Console. WriteLine ("time (. NET):" + tObj. Result (). TotalSeconds );

}

 

Static void BuildArray (int [] arr)

{

For (int I = 0; I & l

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.