Using the Thread Microstates Tool on Solaris Operating Systems - NetBeans IDE 6.8/6.9 Tutorial

Contents

Content on this page applies to NetBeans IDE 6.8 and 6.9
Requirements
Introduction
Setting Up Your Solaris Environment for the Tutorial
Create the Project for the Tutorial
Set the Project Properties
Build and Run the ProfilingDemo Project
Explore Thread Microstates
Thread State Definitions
See Also
Summary

Requirements

To follow this tutorial, you need the following software.

Software Version Required
Solaris 10 or OpenSolaris Operating Systems OpenSolaris, Solaris OS version 10
NetBeans IDE (including C/C++ support) Version 6.8 or 6.9
Java Development Kit (JDK) Version 6
C and C++ compilers, make, gdb The tools versions shown for Solaris in:
C/C++ Tool Collections Tested with NetBeans IDE

See the NetBeans IDE 6.9 Installation Instructions and Configuring the NetBeans IDE for C/C++/Fortran
for information about downloading and installing the required NetBeans software.

Introduction

NetBeans IDE 6.9 with the C/C++/Fortran plugin features the Thread Microstates tool for observing the execution states of threads. The tool shows an overall view of the changing runtime states of your project's threads, and a more detailed view of the state of individual threads. You can detect runtime problems in your applications that might not be detectable when debugging your code.

This tutorial demonstrates how to use the Thread Microstates tool for C/C++ projects running on Solaris 10 or OpenSolaris operating systems. The tool is supported only on Solaris operating systems because Solaris microstate accounting technology and the DTrace utility are required to gather the thread state data. The Thread Microstates tool runs by default when you run your NetBeans project on Solaris OSes.

If you are running the IDE on Linux, Windows, or MacOS X client and have a Solaris system available on your network, you can set up your project to use the Solaris system as a remote development host. Remote development would enable you to use the Thead Microstates profiling tool and other Solaris-based tools even when you run the IDE in Linux, Windows, or MacOS X. See the C/C++ Remote Development Tutorial for more information about how to set up to build on a remote development host.

This tutorial uses a project running on a Solaris SPARC processor-based system. You can follow the steps of the tutorial if you run NetBeans IDE 6.9 on Solaris or OpenSolaris on SPARC-based or x86-based systems. Note that this tutorial uses "Solaris operating systems" to mean both OpenSolaris and Solaris 10 operating systems.

Solaris Microstate Accounting

Many operating systems gather CPU statistics with every CPU clock cycle, or at a fixed time interval. Solaris operating systems use a technology called microstate accounting to gather statistics from the CPU and threads, for every event. Each thread's activity is tracked and the system records the time when each thread transitions from one execution state to another. These timestamps enable you to see how much time a thread spends running, sleeping, waiting, blocked, and so on. The technique enables very accurate statistics to be gathered without adding significant system overhead.

For more information about microstate accounting, see Sun engineer Eric Schrock's informative blog about Microstate accounting in Solaris 10.

Setting Up Your Solaris Environment for the Tutorial

In order to use the Thread Microstates tool, the Solaris user account that you use when you run NetBeans must have sufficient DTrace privileges to observe system behavior. The user account must have the dtrace_user, dtrace_proc, and dtrace_kernel privileges.

If you are running your project on a Solaris remote development host, the DTrace privileges must be set for your user account on the remote host.

To check your DTrace privileges, type the following at the command prompt:
/bin/ppriv $$

If your account has the required privileges, the ppriv command should return something similar to:

E: basic,dtrace_kernel,dtrace_proc,dtrace_user
I: basic,dtrace_kernel,dtrace_proc,dtrace_user
P: basic,dtrace_kernel,dtrace_proc,dtrace_user
L: all

The line that starts with "I:" is important because it specifies privileges that are inherited by programs started from your shell. If your account doesn't have the required inheritable privileges, and you do not have administrator privileges or root access to your system, you should ask your system administrator to add the dtrace_user, dtrace_proc, and dtrace_kernel inheritable privileges to your account.

If you have administrator privileges or root access to your system, you can grant your user account the required privileges as described below.

To permanently grant required DTrace privileges to a user account:
  1. Make sure the user account whose privileges you want to modify is logged out of the system.
  2. Log in as superuser (root) or another administrator user.
  3. Type the following at the command prompt, and replace username with the user account name you are modifying:
    $ usermod -K defaultpriv=basic,dtrace_kernel,dtrace_user,dtrace_proc username
You can then log in to the user account, start the NetBeans IDE, and use the profiling tools with the DTrace data provider.

To temporarily grant required DTrace privileges to a user account:

  1. Type the following to determine the process ID of the shell's process:
    $ echo $$
  2. Become superuser (root) or another administrator user.
  3. Type the following, and replace process-ID with the process ID that was returned from the echo command :
    $ ppriv -s I+dtrace_user,dtrace_proc,dtrace_kernel process-ID
All commands typed in the shell specified by process-ID now inherit the required privileges. The user account can start the NetBeans IDE in this shell and use the Thread Microstates profiling tool.

Create the Project for the Tutorial

To explore the thread microstate profiling features, we'll create a new project from the ProfilingDemo sample application, which is included in the IDE.

The ProfilingDemo application has three stages in which it performs two tasks repeatedly for 10 seconds, using three different techniques to generate some interesting activity to show in the profiling tools. The first task is to write some data to a file, and the second task is to perform some calculations. Each set of two tasks is performed a number of times that is equal to the number of CPUs detected on the development host. For a single-processor system, the program performs the two tasks one time. For a development host having 32 cores, the program performs the two tasks 32 times. You must press the Enter key to begin each set of tasks, so you have to pay attention.

The ProfilingDemo's stages are as follows:

To create the ProfilingDemo project

  1. Open the New Project wizard by choosing File > New Project.
  2. In the wizard, select the Samples category, and then the C/C++ subcategory.
  3. Select the Profiling Demo sample as shown in the figure and click Next.

    Screenshot for creating
      new project from Profiling Demo sample
  4. You can choose the name of the project and the location of the project. Here we use the default ProfilingDemo_1 in our NetBeansProjects directory.
  5. Click Finish to exit the wizard and create the project.

Set the Project Properties

  1. Right-click the ProfilingDemo_1 project node in the Projects tab, and select Properties.
  2. Select the Build node in the Categories panel.
  3. Select SunStudio_12 as the Tool Collection and click Apply.

  4. Screenshot for
           selecting project's tool collection


    You can also use the GNU tool collection because the Thread Microstates tool does not rely on Sun Studio tools.

  5. Select the Run node in the Categories panel. For the Console Type, select Output Window and click Apply. This enables you to see the program output in the IDE's Output Window instead of an external terminal window, as shown in this tutorial.

  6. Screenshot for
          selecting project's console output


  7. Select the Profile node in the Categories panel. Select Show profiling indicators during run.
  8. For the Profile Configuration, select C/C++ DTrace Extended.

  9. Screenshot for
           selecting project's Profile options
  10. Click OK in the Project Properties dialog box.

Build and Run the ProfilingDemo Project

  1. Right-click the ProfilingDemo project node and select Build.
  2. The Output tab shows the results of the build, similar to that shown below. If you see warnings about argument mismatches, you can ignore them.

  3. Building Profiling Demo


  4. Right-click the ProfilingDemo project node and select Run.
    Press Enter whenever you are prompted during the run of the ProfilingDemo project. The output looks similar to the screenshot below.
  5. Sequential demo output
  6. The Run Monitor tab opens to display the dynamic graph for the Thread Microstates tool, and all the other tools specified in the C/C++ DTrace Extended profile configuration.
    In the following screenshot, all the tools are displayed, with the Thread Microstates tool highlighted in red.
  7. If you want to see all the tools, you might need to increase the size of the Run Monitor tab by clicking and dragging the top border of the Run Monitor tab upwards. You can also drag the right side to make them wider.


  8. Notice in the output window the ProfilingDemo program tells you what it is doing so you can match it to the data that the IDE is representing graphically in the tools. For example, the program displays how much memory it is allocating, performs calculations, and then frees the memory. You can see the graphs reflect the program's activity.

Explore Thread Microstates

The Thread Microstates graph in the Run Monitor window shows an overview of the program's threads as they enter various execution states during the project's run. The Solaris microstate accounting feature uses the DTrace facility to provide fine-grained information about the state of each thread as it enters and exits ten different execution states.

The Thread Microstates tool graphically shows summarized state information for all the threads that are created during the project run. Only four states are shown: Sleeping, Waiting, Blocked, and Running. These states represent a simplified or summary view of ten possible microstates, and give an overview of the states of all the threads running in your program. For example, the time spent in the Running state represents all types of running states: running in user mode, running in system calls, running in page faults, running in traps.

  1. The screenshot below was taken at the beginning of the program's run, during the SEQUENTIAL DEMO portion, in which two tasks are run one after the other in a single thread. The points where the thread is sleeping correspond to the points where the program is waiting for you to press Enter.


  2. At the bottom of the Run Monitor window, notice there is a scroll bar. Click and drag it to the left and right so that you can view the data in all the profiling tools, from the beginning of the run time to the end.
  3. Notice in the screenshot below at about 0:42 seconds, the number of threads shown in Thread Microstates jumps to three as the program enters the PARALLEL DEMO portion. The main thread launches two additional threads to run two tasks in parallel, each in its own thread. You can see that there is a lot of time spent in the Waiting state (yellow) and the Sleeping state (blue), and not so much in the Running state (green). No time is spent in the Blocked state (orange) during the PARALLEL DEMO portion because this portion of the program does not implement any thread synchronization tactics such as mutex locks which would block threads.


  4. Notice in the screenshot below at about 0:56 seconds, the Blocked microstate shown in orange appears for the first time during the program run. This corresponds to the point where the program enters the PTHREAD MUTEX DEMO portion, in which each thread uses mutual exclusion locks to prevent other threads from interfering at certain points. Each thread can only run actively after it obtains the mutex lock. A thread is blocked when it tries to access a locked section of code when another thread owns the mutex lock. The use of mutual exclusion locks prevents the threads from entering a data race condition, where the threads have overlapping access to the same data.

  5. Click the Thread Details button to display details about the thread microstates.
    The Thread Details tab opens to display a graphic timeline representation of all the threads run in the program, along with detailed state information.


  6. The Thread Details show the state transitions for each thread during the complete run time of the program. Lets explore this window a bit to see what you can do here.

  7. Move (but don't click) the mouse pointer over one of the colored areas of a thread and you see a popup displaying details about what is going on at that particular moment. Details include the time when the data was taken, and the percentage of time spent in each thread state at that moment. When you move the mouse pointer over the "Summary" area on the right, the popup displays the percentages for the thread's complete run.
  8. Popup showing percentage of time in each thread state

  9. You can control what is shown in the Thread Details window by altering several settings:

    • Click the Detail Level to select the level of detail you want to see. The options are Basic, Moderate, or Advanced, with the simplest view showing only four generalized execution states, and the most complex view showing ten microstates.
    • Click the Show list, and select which type of threads to display. Finished Threads Only shows only those threads that have terminated during the program run. Live Threads Only shows only threads that have not terminated. All Threads shows both live and finished threads.
    • Click on an individual thread and notice that the thread is highlighted. Then press the Shift key and click another thread to select a range of threads. You can also select multiple threads that are not adjacent by pressing the Control key before clicking the threads you are interested in. When the threads you want are highlighted, right-click and select Show Only Selected Threads. You can see all the threads again by using the Show list.
    • Right-click a thread and select Thread Name to change from the default thread name style "Thread n" to the name of functions that are executed by the threads.
  10. You can zoom in on the thread graphs to get a closer look and more microstate data by clicking the plus (+) button in the top left of the Thread Details window. You can also zoom out to get a wider look by clicking the minus (-) button. The Show Complete Run button shows data from the entire project run in the Thread Details window without scrolling. Click the button a second time to return to the scrolling view of the thread details.
  11. In the screenshot below, we see the Thread Details window zoomed in. The Thread IDs are thread entry functions, and the Detail Level is set to Advanced.



  12. Click on a particular spot in the Thread Details, and a new Thread Call Stack tab opens below to show a stack dump. Within the stack dump display, you can expand individual nodes in the stack to see the calls in the stack, or right click the top node and select Expand All to see all the calls happening at that time.

    In the screenshot below, we clicked Thread 5 at about 1:03 near the end of the run.


  13. Stack dump shown by clicking in Thread Details
  14. Double-click a function that is not grayed out, such as mutex_threadfunc in the screen below, to open the source file where the function is called.

  15. Source file opened by double-clicking function in the stack dump
  16. Click on a thread in the Thread Details window again. You can navigate along the thread timeline by using the mouse or keyboard.
  17. With the mouse, right-click and select Navigate > Move Caret to Left to move the focus to the left on the currently selected thread. You can also set a point in the timeline by selecting Navigate > Set Caret, which will update the content of the Thread Call Stack. You can switch focus to the Thread Call Stack by selecting Navigate > Go to Stack View.

  18. Navigate in the Thread Details window by right-clicking
  19. To use keyboard shortcuts to navigate the thread timeline in the Thread Details window, press the following keys:
    • Ctrl+LeftArrow and Ctrl+RightArrow to scroll left and right in the thread timeline.
    • Ctrl+DownArrow to select a point in the timeline, which will update the Thread Call Stack for that point.
    • Alt+DownArrow to focus input on the Thread Call Stack window.
    • In the Thread Call Stack you can use the arrow keys and Enter to open source files associated with the functions.

Thread State Definitions

The Solaris thread microstates, shown in the Advanced detail level, are described below.

State Description
User Running The percentage of time the process has spent in user mode.
System Running The percentage of time the process has spent in system mode.
Other running The percentage of time the process has spent in processing system traps etc.
Text page fault The percentage of time the process has spent in processing text page faults.
Data page fault The percentage of time the process has spent in processing data page faults.
Blocked The percentage of time the process has spent waiting for user locks.
Sleeping The percentage of time the process has spent sleeping.
Waiting The percentage of time the process has spent waiting for CPU.

See Also

For more information about the DTrace technology that is used behind the scenes to compile data about the running project, see the BigAdmin DTrace Portal.

The I/O Usage tool is covered in I/O Profiling for C/C++ Projects on Solaris Operating Systems.

The CPU Usage, Thread Usage, and Memory Usage tools are covered in C/C++ Profiling Tutorial.

For other C/C++ tutorials for the NetBeans IDE, see the C/C++ Application Learning Trail.

Summary

This tutorial demonstrated the following points about the Thread Microstates profiling tool: