Forum Discussion
smp_86112
Cirrostratus
Jun 24, 2010Optimizing If statement conditions
I see this examples like this all over the place:
when HTTP_REQUEST {
if { [HTTP::host] equals "www.myhost.com" and [HTTP::uri] equals "/myuri" } {
HTTP::redirect https://[HTTP::host][HTTP::uri]
}
}I am going though a large number of iRules in an attempt to optimize, and I had a thought occur to me while looking at one of mine like this. Shouldn't I be able to consolidate these two conditions into one, and wouldn't it be more efficient? Something like this?
when HTTP_REQUEST {
if { [[HTTP::host][HTTP::uri]] equals "www.myhost.com/myuri" } {
HTTP::redirect https://[HTTP::host][HTTP::uri]
}
}As a practical matter, this iRule generates an error when it is triggered:TCL error: www.myhost.com - invalid command name "www.myhost.com/myuri" while executing "[HTTP::host][HTTP::uri]"
Assuming I can figure out how to properly write this condition (please help???), wouldn't this be more efficient than writing two conditions to evaluate and then compare? If I can get the syntax right, I'll test it out.
14 Replies
- Chris_Miller
Altostratus
Edit - I see what you're saying here...basically, combining http::host and http::uri into one command...I'll look into. Looking at the http command list below...I don't see an option here: http://devcentral.f5.com/wiki/default.aspx/iRules.HTTP - The_Bhattman
Nimbostratus
Hi SMP,
It certainly would seem efficient. You can't do this now within iRules because they are 2 seperate functions in a single if conditional statement. Perhaps another method would be setting the entire URL into a variable then doing the IF comparison.
i.E.when HTTP_REQUEST { set url [HTTP::host][HTTP::uri] if {$::url equals "www.something.com/blah"} { . . . do something . . . } }
Doesn't seem efficient because you end up creating a variable, but it looks cleaner on the IF statement, at least to me.
I hope this helps
Bhattman - The error is coming up because you are surrounding the combined string with brackets. Try replacing the surrounding brackets with quotes (or curly braces if your embedded string contains quotes itself)
when HTTP_REQUEST { if { "[HTTP::host][HTTP::uri]" equals "www.myhost.com/myuri" } { HTTP::redirect https://[HTTP::host][HTTP::uri] } }
I'd be interested in the performance gain with this approach. While the first example does do two string comparisons, they are both operating on the builtin variables which are essentially a memory lookup (ie. no additional memory allocations required) while the combined approach takes those two memory lookups and has to allocated a new temporary string and then do the same number of character comparisons but with the overhead of the memory allocation. On first guess, I would think this would actually be slower, but would love to see the results.
As Colin and I say in our optimization presentations, it's a fine line when optimizing your code. You can go hog wild and make your code the absolute fastest it can be but if it's harder to read and limits maintainability, then the trade-off of a few clock cycles, in most cases, will not be worth it. In my opinion the combined approach is more concise and easier to read and thus would be preferable. But that's just my opinion...
-Joe - The_Bhattman
Nimbostratus
I guess I learned something new.
Bhattman - smp_86112
Cirrostratus
Thank you very much for weighing in on this Joe, adding double-quotes did indeed consolidate the conditions as I expected. Boy, TCL sure isn't Perl is it?
Since you were kind enough to provide valueable insight, I did some analysis. I used ApacheBench Version 2.0.41-dev <$Revision: 1.141 $>. I hit the VIP 100000 times with a maximum number of concurrent connections set to 25. And I ran the test three times for each method. The results are below.
Assuming my methodology is sound, it looks to me like the most effecient in terms of processing cycles is to consolidate the conditions likeif { "[HTTP::host][HTTP::uri]" equals "www.myhost.com/admin" }
The difference is small, but evident. Also, I wonder why the min-cycles is always zero??? I'm running 10.2.0.timing on when HTTP_REQUEST { if { "[HTTP::host][HTTP::uri]" equals "www.myhost.com/admin" } { HTTP::uri "/new_uri" } } ******************** ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11501 event-type HTTP_REQUEST failures 0 max-cycles 121243 min-cycles 0 name myrule priority 500 total-executions 100022 } ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11536 event-type HTTP_REQUEST failures 0 max-cycles 220940 min-cycles 0 name myrule priority 500 total-executions 100016 } ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11366 event-type HTTP_REQUEST failures 0 max-cycles 105512 min-cycles 0 name myrule priority 500 total-executions 100015 }timing on when HTTP_REQUEST { if { [HTTP::host] equals "www.myhost.com" and [HTTP::uri] equals "/admin" } { HTTP::uri "/new_uri" } } ******************** ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11877 event-type HTTP_REQUEST failures 0 max-cycles 112904 min-cycles 0 name myrule priority 500 total-executions 100015 } ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11751 event-type HTTP_REQUEST failures 0 max-cycles 148691 min-cycles 0 name myrule priority 500 total-executions 100018 } ltm rule-event myrule:HTTP_REQUEST { aborts 0 avg-cycles 11810 event-type HTTP_REQUEST failures 0 max-cycles 77001 min-cycles 0 name myrule priority 500 total-executions 100014 } - I knew I liked that approach for a reason B-).
Not sure about the min-cycles but most likely sounds like a bug to me. We typically say to ignore the min and max values anyway as they are typically skewed by the first run of the iRule.
-Joe - smp_86112
Cirrostratus
I agree with you Joe,. To me, the consolidated conditions is more readable - and based on my testing, it's faster. It surprises me that I don't see this alternative used much on devcentral. In fact, I haven't found it anywhere. - JRahm
Admin
Could be due to the fact that HTTP::host is not case sensitive but HTTP::uri is (or can be in non-windows environments), so combining them might require additional tests, or a string tolower wrapper. - hoolio
Cirrostratus
Interesting testing. I would think the combined check of HTTP::host and HTTP::uri together compared with separate checks won't be as efficient if the request hostname doesn't match what's in the iRule. It would also not make sense to do a combined check if you want to check for multiple URIs.
Aaron - Michael_Yates
Nimbostratus
I would be interested in seeing the test results from adding the a string tolowrapper that Jason pointed out.
smp, if you run that test can you post the results so that we can see the impact of the additional processing?
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
