7 Replies Latest reply on Mar 3, 2014 9:49 AM by Reed Powell

    Optimise CFHTTP Requests/Requests Being Throttled?

    cpb07 Level 1

      I currently have an application that trades virtual items and is making at least 40 CFHTTP requests per second to the host's server.

       

      The issue I'm encountering is that it's taking anywhere from 400ms+ for my CFHTTP call to return a response which means my application is missing out on 99% of the deals it finds, as there are lots of other competiting applications out there that are getting a faster response.

       

      I've struggled to find a cause and/or a solution to this situation so I wrote a script in both CF and C# that makes 10 http requests timing each one which resulted in the following response times:

       

      In CF using the following browsers:

       

      IE9: 384, 444, 302, 570, 535, 317, 510, 349, 357, 467 - Average 423.5ms

      Firefox 27.0.1: 354, 587, 291, 480, 437, 304, 537, 322, 286, 652 - Average 425ms

      Chrome: 300, 328, 328, 639, 285, 259, 348, 291, 299, 414 - Average 349.7ms

       

      In C# Console Application:

       

      597, 43, 96, 52, 44, 305, 67, 91, 54, 270 - Average 161.9ms

       

      As you can see there is a big performance difference when making an HTTPWebRequest in a C# Console Application which is making me think that perhaps the CFHTTP requests are being throttled? Or could it maybe be something to do with the browsers?

       

      Any help would be greatly appreciated! 

        • 1. Re: Optimise CFHTTP Requests/Requests Being Throttled?
          BKBK Adobe Community Professional & MVP

          You might be worrying for nothing. There are apparently 2 different processes at work here:

           

          1) CFHTTP is itself a browser! It interacts with the host server;

          2) IE, Firefox and Chrome each interacts with ColdFusion, via the web server, to get the result of the CFHTTP action.

           

          Your priority is of course for process 1 to be as fast as possible. It is indeed possible that process 1 is super fast, and that process 2 is causing most of the delay that you observe.

           

          To verify this, go to the Debugging page of the ColdFusion Administrator and check the options Enable Request Debugging Output and Report Execution Times. Then examine the execution times of the page containing the CFHTTP code.

           

          In use-cases where reaction speed is critical, one technology comes to mind, push technology. You could redesign your application to use websockets. It would then be possible to get the response from the host server as soon as ColdFusion receives it.

          1 person found this helpful
          • 2. Re: Optimise CFHTTP Requests/Requests Being Throttled?
            cpb07 Level 1

            Thanks for your reply.

             

            Below is a screen dump of the test page I set up which makes 10 requests to a test function. The test function makes a standard CFHTTP call. Each request is timed and the time output on the page.

            ExecutionTime.jpg

            From what's there it gives no insight to me of what is actually happening or causing the requests to take so long to complete.

             

            I've had a look around online the last few hours for web socket example but can find nothing other than creating a chat room! Do you have a link to any material or pseudo code that would allow me to create a test page that used web sockets so I could make a comparison between the request times?

            • 3. Re: Optimise CFHTTP Requests/Requests Being Throttled?
              BKBK Adobe Community Professional & MVP

              I thought your application involved just CFM pages that implement CFHTTP. Hence my suggestion to enable Debugging Output in the Administrator.

               

              From the look of it, your application involves invoking CFCs. This calls for a change of plan. You should de-activate Debugging Output. It is a very blunt instrument in the circumstances.

               

              The cftimer tag or getTickCount function are more appropriate. I guess you are using them already.

               

              The question remains how to crank up the speed in this new setting. Invoking a function in a CFC to interact with a remote server can be costly in CPU terms. I'll have a think.

              • 4. Re: Optimise CFHTTP Requests/Requests Being Throttled?
                cpb07 Level 1

                Thanks, you have no idea how much I appreciate your help with this

                • 5. Re: Optimise CFHTTP Requests/Requests Being Throttled?
                  BKBK Adobe Community Professional & MVP

                  I have tested a number of CFHTTP scenarios. There is good news and bad news.

                   

                  Firstly, the bad news. It seems that CFHTTP is sluggish by design. No amount of refactoring or code-efficiency that I implemented could get it to run faster than a modest threshold.

                   

                  To emulate your scenario, I did the following tests:

                   

                  TestComp.cfc

                   

                  cfcomponent>  

                      <cffunction name="getURL" returntype="struct">

                          <cfhttp method="get" url="http://www.myDomain.com">

                          <cfreturn cfhttp>

                      </cffunction>

                  </cfcomponent>

                   

                  Test scenario 1

                   

                  The following CFM page invokes the CFC 10 times. Each invocation creates an instance of the component, then calls a method that makes a CFHTTP Get request and returns the result as a struct. The result is stored as an array element. Each such invocation is timed.

                   

                  cfhttpTest1.cfm

                   

                  <cfset arr=arrayNew(1)>

                  <!--- <cfset obj=createobject("component","TestComp")> --->

                  <cfloop from="1" to="10" index="i">

                      <cfset start = getTickCount()>

                      <cfset obj=createobject("component","TestComp")>

                      <cfset arr[i] = obj.getURL()>

                      <cfoutput>count #i#: #getTickCount() - start# milliseconds<br></cfoutput>

                  </cfloop>

                   

                  Scenario 1 result

                   

                  count 1: 1665 milliseconds

                  count 2: 1774 milliseconds

                  count 3: 1634 milliseconds

                  count 4: 1771 milliseconds

                  count 5: 1667 milliseconds

                  count 6: 2045 milliseconds

                  count 7: 1645 milliseconds

                  count 8: 3004 milliseconds

                  count 9: 1656 milliseconds

                  count 10: 1844 milliseconds

                   

                  Instantiating the component object outside the loop made no difference in the execution times.

                   

                  Test scenario 2

                   

                  Here the CFHTTP tag comes in as an included CFM file, rather than via a method in a CFC. The hope is that this will be much faster than the above scenario, as there is no object creation and no method invocation. As before, the CFHTTP Get request is run 10 times and the resulting struct is stored as an array element.

                   

                  cfhttpRequest.cfm

                   

                  <cfhttp method="get" url="http://www.myDomain.com">

                   

                   

                  cfhttpTest2.cfm

                   

                  <cfset arr=arrayNew(1)>

                  <cfloop from="1" to="10" index="i">

                      <cfset start = getTickCount()>

                      <cfinclude template="cfhttpRequest.cfm">

                      <cfset arr[i] = cfhttp>

                      <cfoutput>count #i#: #getTickCount() - start# milliseconds<br></cfoutput>

                  </cfloop>

                   

                  Scenario 2 result

                   

                  count 1: 1678 milliseconds

                  count 2: 1740 milliseconds

                  count 3: 1894 milliseconds

                  count 4: 1695 milliseconds

                  count 5: 1769 milliseconds

                  count 6: 1721 milliseconds

                  count 7: 1538 milliseconds

                  count 8: 1683 milliseconds

                  count 9: 1569 milliseconds

                  count 10: 1795 milliseconds

                   

                  Scenario 2 is faster than scenario 1, but only marginally. So, sadly, I have to confirm your findings. I cannot think of any other way to make the CFHTTP requests faster in these scenarios. CFHTTP seems to be slow by design. That was then the bad news.

                   

                  On to the good news. I found a much faster alternative to CFHTTP, namely, Curl.

                   

                  Test scenario 3

                   

                  My Operating System is 64 Bit Windows 7. I downloaded the latest Curl file curl-7.35.0-win64.zip and extracted it to c:\curl-7.35.0-win64. I then ran Curl in ColdFusion, using cfexecute. The loop runs 10 times, as before, each result, being stored as a text file.

                   

                  curlTest.cfm

                   

                  <cfset outputPath=arrayNew(1)>

                  <cfloop from="1" to="10" index="i">

                      <cfset start = getTickCount()>

                      <cfset outputPath[i]= "C:\Temp\output#i#.txt">

                      <cfexecute name = "C:\curl-7.35.0-win64\bin\curl.exe"

                          arguments = "http://www.myDomain.com"

                          outputFile = "#outputPath[i]#">

                      </cfexecute>

                      <cfoutput>count #i#: #getTickCount() - start# milliseconds<br></cfoutput>

                  </cfloop>

                   

                  Scenario 3 result

                   

                  count 1: 392 milliseconds

                  count 2: 128 milliseconds

                  count 3: 119 milliseconds

                  count 4: 191 milliseconds

                  count 5: 49 milliseconds

                  count 6: 12 milliseconds

                  count 7: 24 milliseconds

                  count 8: 23 milliseconds

                  count 9: 6 milliseconds

                  count 10: 21 milliseconds

                   

                  Evidently, Curl is faster than CFHTTP is this scenario, by several orders of magnitude!

                  1 person found this helpful
                  • 6. Re: Optimise CFHTTP Requests/Requests Being Throttled?
                    cpb07 Level 1

                    Wow!! Thanks very much for this!

                     

                    I'll have a look into cURL and see how customisable it is (to pass in custom header values) and report back.

                    • 7. Re: Optimise CFHTTP Requests/Requests Being Throttled?
                      Reed Powell Level 3

                      I've always thought that CFHTTP had alot of overhead.  a year or two ago we were looking at switching to php (have since dropped that in favor of .NET), and had a php programmer convert one of our really slow CFHTTP laden scripts.  The php script used curl for all of the HTTP handling.  It ran so fast I didn't think it did anything.  We're talking about going from hours of processing to a minute or so, doing around 100,000 calls to a google API.

                       

                      One of the nice things about curl is that if you have problems with ssl sites you can set an option to ignore certificate errors.

                       

                      The .NET rewrite also saw gains in performance over CFHTTP in CF, but not quite to the level of what we saw above.