1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
<?xml version='1.0'?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<section id="associativearrays">
<title>Associative Arrays</title>
<indexterm>
<primary>arrays</primary>
<seealso>associative arrays</seealso>
</indexterm>
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
</indexterm>
<para>SystemTap also supports the use of associative arrays. While an ordinary variable represents a single value, associative arrays can represent a collection of values. Simply put, an associative array is a collection of unique keys; each key in the array has a value associated with it.</para>
<!--<para>SystemTap also supports the use of associative arrays. While an ordinary variable represents a single value, associative arrays can represent a list of values. Simply put, an associative array is a collection of unique keys; each key in the array has a value associated with it. Illustrating this visually would be similar to creating a two-column table: the first column would have the unique key, while the second column would have each key's associated value. Each unique key and its associated value is referred to as a <emphasis>key pair</emphasis>.</para>-->
<!-- next 2 indexterms for key pairs -->
<!--
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>key pairs</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>key pairs</tertiary>
</indexterm>
<indexterm>
<primary>key pairs</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<!-- next 2 indexterms for unique keys
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>unique keys</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>unique keys</tertiary>
</indexterm>
<indexterm>
<primary>unique keys</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<!-- next 2 indexterms for associated values
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>associated values</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>associated values</tertiary>
</indexterm>
<indexterm>
<primary>associated values</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<!-- next 2 indexterms for index expression
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>index expression</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>index expression</tertiary>
</indexterm>
<indexterm>
<primary>index expression</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<para>Since associative arrays are normally processed in multiple probes (as we will demonstrate later), they should be declared as <command>global</command> variables in the SystemTap script. The syntax for accessing an element in an associative array is similar to that of <command>awk</command>, and is as follows:</para>
<!-- next 3 indexterms for syntax
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>syntax</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>syntax</tertiary>
</indexterm>
<indexterm>
<primary>syntax</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<indexterm>
<primary>format</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<screen><replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>]</screen>
<para>Here, the <command><replaceable>array_name</replaceable></command> is any arbitrary name the array uses. The <command><replaceable>index_expression</replaceable></command> is used to refer to a specific unique key in the array. To illustrate, let us try to build an array named <command>foo</command> that specifies the ages of three people <command>tom</command>, <command>dick</command>, and <command>harry</command> (which are unique keys). To assign them the ages (associated values) of 23, 24, and 25 respectively, we'd use the following array statements:</para>
<!-- next 2 indexterms for example
<indexterm>
<primary>arrays</primary>
<secondary>introduction</secondary>
<tertiary>example</tertiary>
</indexterm>
-->
<indexterm>
<primary>associative arrays</primary>
<secondary>introduction</secondary>
<tertiary>example</tertiary>
</indexterm>
<indexterm>
<primary>example</primary>
<secondary>introduction</secondary>
<tertiary>arrays</tertiary>
</indexterm>
<example id="arraysimplestexample">
<title>Basic Array Statements</title>
<screen>foo["tom"] = 23
foo["dick"] = 24
foo["harry"] = 25</screen>
</example>
<para>You can specify up to nine index expressions in an array statement, each one delimited by a comma (<command>,</command>). This is useful if you wish to have a key that contains multiple pieces of information. The following line from <xref linkend="scriptdisktop"/> uses 5 elements for the key: process ID, executable name, user ID, parent process ID, and string "W". It associates the value of <command>devname</command> with that key.</para>
<screen>device[pid(),execname(),uid(),ppid(),"W"] = devname</screen>
<important>
<title>Important</title>
<para>All associate arrays must be declared as <command>global</command>, regardless of whether the associate array is used in one or multiple probes. </para>
</important>
<!--
<varlistentry>
<term></term>
<listitem>
<para></para>
</listitem>
</varlistentry>
-->
<!--
<para>SystemTap supports numerous ways to manipulate associative arrays (i.e. <command><replaceable>operation</replaceable></command> in the syntax format). For the purposes of this book, we will only cover the most common examples of manipulating associative arrays, all of which appear in <xref linkend="useful-systemtap-scripts"/>.</para>
<formalpara id="aaexamplesimple">
<title>Incrementing Associated Values of Unique Keys</title>
<para>The simplest form of data manipulation in associative arrays is incrementing the associated value of a unique key in the array. The syntax for this operation is as follows:</para>
</formalpara>
<screen><replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>"] ++</screen>
<para>Here, the <command>++</command> operation instructs SystemTap to increment the associated value of <command><replaceable>unique_key</replaceable></command> by <command><replaceable>value</replaceable></command>. For example, to increase the associated value of unique key <command>hello</command> in array <command>foo</command> by 4, use:</para>
<formalpara id="aaexamplesimple-example">
<title>explicit-incrementing-in-arrays.stp</title>
<para>
<programlisting>probe begin { foo[4,"hello"] ++ }</programlisting>
</para>
</formalpara>
<formalpara id="aaexampleupdatecounting">
<title>Incrementing Associated Values of Unique Keys (By Variable)</title>
<para>One of the most common uses of associative arrays is to tally events per unique key. To do this, use the operator <command>+= $count</command>, as in:</para>
</formalpara>
<screen><replaceable>array_name</replaceable>[<replaceable>unique_key</replaceable>] += $count </screen>
<para>You can also use a handler function in as the <command><replaceable>unique_key</replaceable></command>. Doing so creates an associate array that uses the values returned by the handler function as the unique keys. The first time that a probe using this array returns a string value, that value is set as a unique key with an initial value of 0. The next time that the probe returns the same string value, it increments the associated value of the unique key by 1.</para>
<para>For example, let's say you need to tally how many times each process performs a read to the virtual file system (VFS). To do this, probe the VFS read opeartion, use the handler <command>execname()</command> to identify which processes performed the VFS read, and tally the reads of each process using the associative array named <command>reads</command>, as in</para>
<formalpara id="aaexamplesimplevfsreads">
<title>tallying-in-arrays.stp</title>
<para>
<programlisting>probe vfs.read
{ reads[execname()] += $count }</programlisting>
</para>
</formalpara>
<para>In <xref linkend="aaexamplesimplevfsreads"/>, the first time that the probe returns the process name <command>gnome-terminal</command> (that is, the first time <command>gnome-terminal</command> performs a VFS read), that process name is set as a unique key. The next time that the probe returns the process name <command>gnome-terminal</command>, SystemTap increments the associated value of <command>gnome-terminal</command> by 1. SystemTap performs this operation for <emphasis>all</emphasis> process names as the probe returns them.</para>
-->
</section>
|