{"id":631,"date":"2016-04-09T19:40:15","date_gmt":"2016-04-09T19:40:15","guid":{"rendered":"http:\/\/nenadnoveljic.com\/blog\/?p=631"},"modified":"2018-05-17T16:15:41","modified_gmt":"2018-05-17T16:15:41","slug":"emulex-hba-driver-performance-analysis-measuring-overhead","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/","title":{"rendered":"Emulex HBA Driver Performance Analysis (3) &#8211; Measuring Overhead"},"content":{"rendered":"<h1>Introduction<\/h1>\n<p>In <a href=\"http:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/\" target=\"_blank\">the previous installment<\/a>\u00a0I wrote about the processing workflow within the Emulex HBA driver. Three processing stages were identified: I\/O start, I\/O interrupt and I\/O. In this blog post I&#8217;ll\u00a0explain the internal functioning of the DTrace script which I developed for measuring\u00a0the duration of each stage and the total amount of time spent in the driver code.<\/p>\n<h1>Setting Boundaries<\/h1>\n<p>The fbt probes will be used for recording the timestamps at the beginning and the end of each stage. Therefore, the appropriate functions need to be identified. The entry probe of the first emlxs function on the stack is a good choice for recording the starting point of\u00a0a processing stage.<\/p>\n<p>Since scripts based on fbt trace raw kernel code, it might happen that they have to be adapted for different kernel and driver releases.<\/p>\n<p>Let&#8217;s\u00a0examine the\u00a0functions for each of the stages.<\/p>\n<h2>I\/O Start<\/h2>\n<p>First, I&#8217;ll collect the stacks for the emlxs functions and identify the stack. The stack for I\/O will contain\u00a0some transport\u00a0functions:<\/p>\n<pre><code>dtrace -n 'fbt:emlxs::entry { @[stack()] = count(); }'\r\n[...truncated...]\r\nemlxs`emlxs_sli4_bde_setup+0x233\r\nemlxs`emlxs_sli4_prep_fcp_iocb+0x10a\r\nemlxs`emlxs_send_fcp_cmd+0x137\r\nemlxs`emlxs_fca_transport+0x256\r\nfctl`fc_ulp_transport+0x22a\r\n[...truncated...]<\/code><\/pre>\n<p>The first emlxs function on the stack is emlxs_fca_transport:<\/p>\n<pre><code>emlxs_solaris.c:\r\nemlxs_fca_transport(opaque_t fca_port_handle, fc_packet_t *pkt)<\/code><\/pre>\n<p>The second argument pkt is the pointer to the packet structure. The address of the buffer will be used to uniquely identify the packet while it&#8217;s traversing\u00a0different stages.<\/p>\n<p>Next, I&#8217;ll verify that the function executes once and only once for each I\/O by looking at the number of executions under load:<\/p>\n<pre><code>dtrace -n 'fbt:emlxs::entry,fbt:fctl:fc_ulp_transport:entry { @[probefunc] = count(); }'\r\n[...truncated...]\r\nfc_ulp_transport        23316\r\n[...truncated...]\r\nemlxs_fca_transport     23316\r\n[...truncated...]\r\n<\/code><\/pre>\n<p>Since this prerequisite is fulfilled, the entry and the return probe can be used to record the timestamp of the beginning and the end of the I\/O start stage, respectively:<\/p>\n<pre><code>\/* I\/O Start Begin *\/\r\nfbt::emlxs_fca_transport:entry\r\n{\r\n  self-&gt;pkt_addr = arg1 ;\r\n  ts_start_begin[self-&gt;pkt_addr] = timestamp ;\r\n}\r\n\r\n\/* I\/O Start End *\/\r\nfbt::emlxs_fca_transport:return\r\n\/ self-&gt;pkt_addr \/\r\n{\r\n  ts_start_end[self-&gt;pkt_addr] = timestamp ;\r\n  self-&gt;pkt_addr = 0 ;\r\n}<\/code><\/pre>\n<h2>I\/O Interrupt<\/h2>\n<p>Second, the stack of the interrupt handler thread will be examined:<\/p>\n<pre><code>[...truncated...]\r\nemlxs`emlxs_mem_put+0x9d\r\nemlxs`emlxs_sli4_free_xri+0xe1\r\nemlxs`emlxs_sli4_process_wqe_cmpl+0xff\r\nemlxs`emlxs_sli4_process_cq+0x139\r\nemlxs`emlxs_sli4_process_eq+0xda\r\nemlxs`emlxs_sli4_msi_intr+0x7f\r\napix`apix_dispatch_by_vector+0x89\r\napix`apix_dispatch_lowlevel+0x32\r\nunix`switch_sp_and_call+0x13\r\n[...truncated...]<\/code><\/pre>\n<p>As the processing\u00a0of the interrupt\u00a0begins with the function emlxs_sli4_msi_intr, the begin timestamp will be collected in the entry probe. However, this function doesn&#8217;t contain any obvious arguments which could identify the scsi packet. From the <a href=\"http:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/\" target=\"_blank\">the previous installment<\/a> we already know that the first function on the stack which could be associated with the packet is emlxs_sli4_process_wqe_cmpl. Therefore, the start time\u00a0has to\u00a0be initialized in the entry probe of emlxs_sli4_msi_intr and then stored in the associative array within the entry probe of emlxs_sli4_process_wqe_cmpl:<\/p>\n<pre><code>\/* I\/O Interrupt Begin *\/\r\nfbt::emlxs_sli4_msi_intr:entry\r\n{\r\n  self-&gt;start_ts_intr = timestamp ;\r\n}\r\n\r\nfbt::emlxs_sli4_process_wqe_cmpl:entry\r\n\/ self-&gt;start_ts_intr \/\r\n{\r\n  self-&gt;pkt_addr \\\r\n    = (int64_t)args[0]-&gt;fc_table[args[2]-&gt;RequestTag]-&gt;pkt ;\r\n  ts_interrupt_begin[self-&gt;pkt_addr] = self-&gt;start_ts_intr ;\r\n}<\/code><\/pre>\n<p>The return probe of fbt::emlxs_sli4_process_wqe_cmpl is suitable for storing the timestamp of the end of the I\/O interrupt stage:<\/p>\n<pre><code>\/* I\/O Interrupt End *\/\r\nfbt::emlxs_sli4_process_wqe_cmpl:return\r\n\/ self-&gt;pkt_addr \/\r\n{\r\n  ts_interrupt_end[self-&gt;pkt_addr] = timestamp ;\r\n}\r\n<\/code><\/pre>\n<h2>I\/O Done (Completion Thread)<\/h2>\n<p>Again, the first thing to do is to explore the stack and find appropriate functions for storing the timestamps:<\/p>\n<pre><code>[...truncated...]\r\nfcp`fcp_cmd_callback+0x72\r\nemlxs`emlxs_handle_fcp_event+0x9fa\r\nemlxs`emlxs_proc_channel_event+0x647\r\nemlxs`emlxs_proc_channel+0x62\r\nemlxs`emlxs_thread+0x169\r\nunix`thread_start+0x8\r\n[...truncated...]<\/code><\/pre>\n<p>emlxs_thread, the first function on the stack, gets executed only during driver initialization, so its entry and return probes can&#8217;t be used for storing the timestamp information. The next choice is emlxs_proc_channel which comes immediately after:<\/p>\n<pre><code>\/* I\/O Done Begin *\/\r\nfbt::emlxs_proc_channel:entry\r\n{\r\n  self-&gt;start_ts = timestamp ;\r\n}<\/code><\/pre>\n<p>The entry probe of fcp_cmd_callback might be a good candidate for recording the end time of an I\/O done operation, because it is the first non-emlxs function on the stack. I&#8217;ll just quickly confirm that it fires once and only once for each I\/O:<\/p>\n<pre><code>dtrace -n 'fbt::fcp_cmd_callback:entry,fbt:fctl:fc_ulp_transport:entry { @[probefunc] = count(); }'\r\nfcp_cmd_callback   14800\r\nfc_ulp_transport   14803<\/code><\/pre>\n<p>Below is the code excerpt for storing the timestamps:<\/p>\n<pre><code>\/* I\/O Done End *\/\r\nfbt::fcp_cmd_callback:entry\r\n\/ ts_start_begin[arg0] &amp;&amp; ts_interrupt_begin[arg0] &amp;&amp; self-&gt;start_ts \/\r\n{\r\n  this-&gt;ts_done_end = timestamp ;\r\n\r\n  this-&gt;pkt_addr = arg0 ;\r\n  this-&gt;ts_done_begin = self-&gt;start_ts ;\r\n  self-&gt;start_ts = 0 ;\r\n[...truncated...]<\/code><\/pre>\n<h1>Elapsed Times<\/h1>\n<p>The flow chart below visualizes the processing stages with the points where the timestamps are collected:<\/p>\n<div id=\"attachment_659\" style=\"width: 1008px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif\" rel=\"attachment wp-att-659\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-659\" class=\"size-full wp-image-659\" src=\"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif\" alt=\"Emulex Flow Chart\" width=\"998\" height=\"358\" \/><\/a><p id=\"caption-attachment-659\" class=\"wp-caption-text\">Emulex Flow Chart<\/p><\/div>\n<p>Note that the interrupt handler puts the packets onto the completion queue which is consumed by the I\/O done (completion) thread.<\/p>\n<p>The timestamps collected according to the flow chart above\u00a0are sufficient\u00a0for\u00a0calculating the elapsed times for each stage:<\/p>\n<pre><code>duration_start = ts_start_end - ts_start_begin \r\nduration_interrupt = ts_interrupt_end - ts_interrupt_begin \r\nduration_done = ts_done_end - ts_done_begin<\/code><\/pre>\n<p>The total elapsed time for an I\/O is the difference between ts_done_end and ts_start_begin:<\/p>\n<pre><code>duration_total = ts_done_end - ts_start_begin<\/code><\/pre>\n<p>The time spent waiting in the completion queue:<\/p>\n<pre><code>duration_queue = ts_done_begin - ts_interrupt_end<\/code><\/pre>\n<p>And now comes the most interesting part: by setting the measurement points as in the flow chart above we can calculate the total elapsed time spent in the driver code, which is the key point for analysing driver&#8217;s performance:<\/p>\n<pre><code>duration_emlxs = duration_start + ts_done_end - ts_interrupt_begin<\/code><\/pre>\n<p>Moreover, we can even calculate how much time in total was spent outside of the Solaris kernel (Emulex HBA, SAN network and SAN storage) without knowing anything about those devices:<\/p>\n<pre><code>duration_external = duration_total - duration_emlxs<\/code><\/pre>\n<h1>emlxsoverhead.d<\/h1>\n<p>I assembled the code excerpts above into the script <a href=\"https:\/\/github.com\/nenadnoveljic\/dtrace\/blob\/master\/emlxsoverhead.d\" target=\"_blank\">emlxsoverhead.d<\/a>. The script\u00a0prints the latency of each I\/O\u00a0and the durations of\u00a0all processing stages. Optionally, the threshold for displaying only longer I\/Os can be provided. For example, the following command will display only I\/Os lasting more than 1 ms:<\/p>\n<pre><code>dtrace -Cs emlxsoverhead.d<\/code><\/pre>\n<p>The script prints following data:<\/p>\n<pre><code>TIMESTAMP:     time when I\/O was performed \r\nTOTAL(us):     I\/O latency measured on the driver \r\nEMLXS(us):     overhead of the driver code \r\nI\/O START(us): duration of the I\/O start stage \r\nI\/O INTR(us):  time spent in the interrupt handler \r\nQUEUE(us):     time spent on the completion queue \r\nI\/O DONE:      time spent on the completion thread<\/code><\/pre>\n<p>Below is the example output:<\/p>\n<pre><code>TIMESTAMP\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 TOTAL(us) EMLXS(us) I\/O START(us)\u00a0 I\/O INTR(us)\u00a0 QUEUE(us) I\/O DONE(us)\r\n2016 Apr\u00a0 9 19:31:21 1028\u00a0\u00a0\u00a0\u00a0\u00a0 35\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 7\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 9\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 12\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6\r\n2016 Apr\u00a0 9 19:31:21 4928\u00a0\u00a0\u00a0\u00a0\u00a0 35\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 8\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 5\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 11\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 10\r\n2016 Apr\u00a0 9 19:31:21 4721\u00a0\u00a0\u00a0\u00a0\u00a0 46\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 6\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 9\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 14\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 16\r\n<\/code><\/pre>\n<p>In the example above, the first I\/O took 1028 microseconds and the most of this time was spent outside\u00a0 the kernel. The longest processing step in the driver was waiting in the completion queue (12 microseconds).<\/p>\n<p>Longer I\/O latencies, where the most time is elapsed\u00a0in the driver code (EMLXS), are not normal and should be investigated further.<\/p>\n<h1>Conclusion<\/h1>\n<p>In this installment I explained how to measure the time spent in each processing stage of the Emulex device driver and provided the script for it. In the next installment I&#8217;ll explain how I analyzed\u00a0a production problem with\u00a0a high latency.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The blog post describes how to measure elapsed time in the Emulex HBA driver. <a href=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[24,15,14],"tags":[],"class_list":["post-631","post","type-post","status-publish","format-standard","hentry","category-dtrace","category-emulex","category-solaris"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"The blog post describes how to measure elapsed time in the Emulex HBA driver.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"The blog post describes how to measure elapsed time in the Emulex HBA driver.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-09T19:40:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-05-17T16:15:41+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Emulex HBA Driver Performance Analysis (3) &#8211; Measuring Overhead\",\"datePublished\":\"2016-04-09T19:40:15+00:00\",\"dateModified\":\"2018-05-17T16:15:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/\"},\"wordCount\":879,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/flow-chart4.gif\",\"articleSection\":[\"DTrace\",\"Emulex\",\"Solaris\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/\",\"name\":\"Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/flow-chart4.gif\",\"datePublished\":\"2016-04-09T19:40:15+00:00\",\"dateModified\":\"2018-05-17T16:15:41+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"The blog post describes how to measure elapsed time in the Emulex HBA driver.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#primaryimage\",\"url\":\"http:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/flow-chart4.gif\",\"contentUrl\":\"http:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/flow-chart4.gif\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-measuring-overhead\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Emulex HBA Driver Performance Analysis (3) &#8211; Measuring Overhead\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics","description":"The blog post describes how to measure elapsed time in the Emulex HBA driver.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/","og_locale":"en_US","og_type":"article","og_title":"Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics","og_description":"The blog post describes how to measure elapsed time in the Emulex HBA driver.","og_url":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/","og_site_name":"All-round Database Topics","article_published_time":"2016-04-09T19:40:15+00:00","article_modified_time":"2018-05-17T16:15:41+00:00","og_image":[{"url":"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif","type":"","width":"","height":""}],"author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Emulex HBA Driver Performance Analysis (3) &#8211; Measuring Overhead","datePublished":"2016-04-09T19:40:15+00:00","dateModified":"2018-05-17T16:15:41+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/"},"wordCount":879,"commentCount":0,"image":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#primaryimage"},"thumbnailUrl":"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif","articleSection":["DTrace","Emulex","Solaris"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/","url":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/","name":"Emulex HBA Driver Performance Analysis (3) - Measuring Overhead - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#primaryimage"},"image":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#primaryimage"},"thumbnailUrl":"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif","datePublished":"2016-04-09T19:40:15+00:00","dateModified":"2018-05-17T16:15:41+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"The blog post describes how to measure elapsed time in the Emulex HBA driver.","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#primaryimage","url":"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif","contentUrl":"http:\/\/nenadnoveljic.com\/blog\/wp-content\/uploads\/2016\/04\/flow-chart4.gif"},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-measuring-overhead\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Emulex HBA Driver Performance Analysis (3) &#8211; Measuring Overhead"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/631","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=631"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/631\/revisions"}],"predecessor-version":[{"id":715,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/631\/revisions\/715"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}