CodeShare
Have some code. Share some code.
cancel
Showing results for 
Search instead for 
Did you mean: 
Custom Alert Banner
JRahm
Community Manager
Community Manager

Problem this snippet solves:

The article Ten Steps to iRules Optimization illustrates some ways to optimize your iRules. I took a look at the control statements and built a little iRule that will test those assertions and generate performance graphs using Google Charts to present the findings.

How to use this snippet:

Dependencies

This iRule relies on external Class files for the test on the "class match" command. The class names should be in the form of "class_xxx" where xxx is the list size you want to test. Include xxx number of entries with values from 0 to xxx-1. For a list size of 10, the class should look like this:

# Snippet in bigip.conf
class calc_10 {
   "0"
   "1"
   "2"
   "3"
   "4"
   "5"
   "6"
   "7"
   "8"
   "9"
}

I used perl to generate larger classes of size 100, 1000, 5000, and 10000 for my tests.

Usage

Assign the iRule to a virtual server and then browse to the url http://virtualserver/calccommands. I've included query string arguments to override the default test parameters as follows

  • ls=nnn - List Size. You will need a class defined titled calc_10 for a value of ls=10.
  • i=nnn - Number of iterations. This will be how many times the test is performed for each list size.
  • gw=nnn - Graph Width (default value of 300)
  • gh=nnn - Graph Height (default value of 200)
  • ym=nnn - Graph Y Max value (default 500)

An example usage is: http://virtualserver/calccommands?ls=1000&i=500. This will work on a list size of 1000 with 500 iterations per test.

Code :

when HTTP_REQUEST {

  #--------------------------------------------------------------------------
  # read in parameters
  #--------------------------------------------------------------------------
  set listsize    [URI::query [HTTP::uri] "ls"];
  set iterations  [URI::query [HTTP::uri] "i"];
  set graphwidth  [URI::query [HTTP::uri] "gw"];
  set graphheight [URI::query [HTTP::uri] "gh"];
  set ymax        [URI::query [HTTP::uri] "ym"];

  #--------------------------------------------------------------------------
  # set defaults
  #--------------------------------------------------------------------------
  if { ("" == $iterations) || ($iterations > 10000) } { set iterations 500; }
  if { "" == $listsize } { set listsize 5000; }
  if { "" == $graphwidth } { set graphwidth 300; }
  if { "" == $graphheight } { set graphheight 200; }
  if { "" == $ymax } { set ymax 500; }
  
  set modulus [expr $listsize / 5];
  set autosize 0;
  
  #--------------------------------------------------------------------------
  # build lookup list
  #--------------------------------------------------------------------------
  set matchlist "0";
  for {set i 1} {$i < $listsize} {incr i} {
    lappend matchlist "$i";
  }

  set luri [string tolower [HTTP::path]]

  switch -glob $luri {
    
    "/calccommands" {
      
      #----------------------------------------------------------------------
      # check for existence of class file.  If it doesn't exist
      # print out a nice error message.  Otherwise, generate a page of
      # embedded graphs that route back to this iRule for processing
      #----------------------------------------------------------------------
      
      if { [catch { class match "1" equals calc_$listsize } ] } {
        
        
        # error
        set content "
BIG-IP Version $static::tcl_platform(tmmVersion)" append content "

ERROR: class file 'calc_$listsize' not found

"; append content ""; } else { # Build the html and send requests back in for the graphs... set content "
BIG-IP Version $static::tcl_platform(tmmVersion)" append content "

List Size: ${listsize}


" set c 0; foreach item $matchlist { set mod [expr $c % $modulus]; if { $mod == 0 } { append content ""; } incr c; } append content "

"; } HTTP::respond 200 content $content; } "/calccommands/*" { #---------------------------------------------------------------------- # Time various commands (switch, switch -glob, if/elseif, matchclass, # class match) and generate redirect to a Google Bar Chart #---------------------------------------------------------------------- set item [getfield $luri "/" 3] set labels "|" set values "" #---------------------------------------------------------------------- # Switch #---------------------------------------------------------------------- set expression "set t1 \[clock clicks -milliseconds\]; \n" append expression "for { set y 0 } { \$y < $iterations } { incr y } { " append expression "switch $item {" foreach i $matchlist { append expression "\"$i\" { } "; } append expression " } " append expression " } \n" append expression "set t2 \[clock clicks -milliseconds\]"; eval $expression; set duration [expr {$t2 - $t1}] if { [expr {$duration < 0}] } { log local0. "NEGATIVE TIME ($item, matchclass: $t1 -> $t2"; } append labels "s|"; if { $values ne "" } { append values ","; } append values "$duration"; if { $autosize && ($duration > $ymax) } { set ymax $duration } #---------------------------------------------------------------------- # Switch -glob #---------------------------------------------------------------------- set expression "set t1 \[clock clicks -milliseconds\]; \n" append expression "for { set y 0 } { \$y < $iterations } { incr y } { " append expression "switch -glob $item {" foreach i $matchlist { append expression "\"$i\" { } "; } append expression " } " append expression " } \n" append expression "set t2 \[clock clicks -milliseconds\]"; eval $expression; set duration [expr {$t2 - $t1}] if { [expr {$duration < 0}] } { log local0. "NEGATIVE TIME ($item, matchclass: $t1 -> $t2"; } append labels "s-g|"; if { $values ne "" } { append values ","; } append values "$duration"; if { $autosize && ($duration > $ymax) } { set ymax $duration } #---------------------------------------------------------------------- # If/Elseif #---------------------------------------------------------------------- set z 0; set y 0; set expression "set t1 \[clock clicks -milliseconds\]; \n" append expression "for { set y 0 } { \$y < $iterations } { incr y } { " foreach i $matchlist { if { $z > 0 } { append expression "else"; } append expression "if { $item eq \"$i\" } { } "; incr z; } append expression " } \n"; append expression "set t2 \[clock clicks -milliseconds\]"; eval $expression; set duration [expr {$t2 - $t1}] if { [expr {$duration < 0}] } { log local0. "NEGATIVE TIME ($item, matchclass: $t1 -> $t2"; } append labels "If|"; if { $values ne "" } { append values ","; } append values "$duration"; if { $autosize && ($duration > $ymax) } { set ymax $duration } #---------------------------------------------------------------------- # Matchclass on list #---------------------------------------------------------------------- set expression "set t1 \[clock clicks -milliseconds\]; \n" append expression "for { set y 0 } { \$y < $iterations } { incr y } { " append expression "if { \[matchclass $item equals \$matchlist \] } { }" append expression " } \n"; append expression "set t2 \[clock clicks -milliseconds\]"; eval $expression; set duration [expr {$t2 - $t1}] if { [expr {$duration < 0}] } { log local0. "NEGATIVE TIME ($item, matchclass: $t1 -> $t2"; } append labels "mc|"; if { $values ne "" } { append values ","; } append values "$duration"; if { $autosize && ($duration > $ymax) } { set ymax $duration } #---------------------------------------------------------------------- # class match (with class) #---------------------------------------------------------------------- set expression "set t1 \[clock clicks -milliseconds\]; \n" append expression "for { set y 0 } { \$y < $iterations } { incr y } { " append expression "if { \[class match $item equals calc_$listsize \] } { }" append expression " } \n"; append expression "set t2 \[clock clicks -milliseconds\]"; log local0. $expression; eval $expression; set duration [expr {$t2 - $t1}] if { [expr {$duration < 0}] } { log local0. "NEGATIVE TIME ($item, matchclass: $t1 -> $t2"; } append labels "c|"; if { $values ne "" } { append values ","; } append values "$duration"; if { $autosize && ($duration > $ymax) } { set ymax $duration } #---------------------------------------------------------------------- # build redirect for the google chart and issue a redirect #---------------------------------------------------------------------- set mod [expr $item % 10] set newuri "http://${mod}.chart.apis.google.com/chart?chxl=0:${labels}&chxr=1,0,${ymax}&chxt=x,y" append newuri "&chbh=a&chs=${graphwidth}x${graphheight}&cht=bvg&chco=A2C180&chds=0,${ymax}&chd=t:${values}" append newuri "&chdl=(in+ms)&chtt=Perf+(${iterations}-${item}/${listsize})&chg=0,2&chm=D,0000FF,0,0,3,1" HTTP::redirect $newuri; } } }
Comments
keithhubb
F5 Employee
F5 Employee

Would it be possible to update this code for the newer Google chart apis?

keithhubb
F5 Employee
F5 Employee

Hi, after requesting an updated script, I took upon myself to make the modifications. I switched the charting engine to quickchart.io, which should be stable(ish) for the next several years. I also inserted some addition remarks with use examples.

 

😀

Version history
Last update:
‎17-Mar-2015 12:16
Updated by:
Contributors