Announcement

Collapse
No announcement yet.

Slow price response times compared with vendor apps.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Slow price response times compared with vendor apps.

    I've spent a few weeks investigating the response time on the new API-NG. Using various ServicePointManager settings and varying request headers, the lowest response time I can get for a single market is approx 50ms.

    I've tested both endpoints JSON and REST and both give roughly the same performance.

    I've also tested various 3rd party applications that are on the Vendor Program and they are reporting response times about 20ms faster on the same market.

    vendor1 = 30ms - 35ms
    vendor2 = 31ms - 40ms
    vendor3 = 30ms - 35ms

    Do apps on the vendor program get priority/faster responses? Are other people experiencing similar differences?

    Can anyone suggest any further improvements to get the same speed as the vendors?

    If anyone wants to test, below is some C# code that tests both the REST and JSON endpoints, the code runs on a form with 2 buttons and 3 textboxes.

    Just change user details in
    Code:
            private string m_AppKey = "<APPKEYHERE>";
            private string username = "USERNAME";
            private string password = "PASSWORD";
            private string m_marketId = "1.116868859";

    Code:
        public partial class Form1 : Form
        {
    
            //Add reference to Newtonsoft.Json
            private string m_SSOID;
            private string m_AppKey = "<APPKEYHERE>";
            private string username = "USERNAME";
            private string password = "PASSWORD";
            private string m_marketId = "1.116868859";
            private Stopwatch stopwatch = new Stopwatch();
           
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                textBox2.Text = "";
                stopwatch.Reset();
                stopwatch.Start();
                textBox2.Text = JsonEndPoint();
                stopwatch.Stop();
                textBox3.Text = stopwatch.Elapsed.ToString();
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                textBox2.Text = "";
                stopwatch.Reset();
                stopwatch.Start();
                textBox2.Text = RestEndPoint();
                stopwatch.Stop();
                textBox3.Text = stopwatch.Elapsed.ToString();
            }
    
            private string JsonEndPoint()
            {
                string endPoint = "https://api.betfair.com/exchange/betting/json-rpc/v1/";
                string method = "SportsAPING/v1.0/listMarketBook";
                string result = "";
    
                ServicePointManager.Expect100Continue = false;
                ServicePointManager.DefaultConnectionLimit = 200;
                ServicePointManager.MaxServicePointIdleTime = 2000;
    
                if (m_SSOID == null)
                    nonInteractiveLogin();
    
                IList<string> marketIds = new List<string>();
                marketIds.Add(m_marketId);
                ISet<PriceData> priceData = new HashSet<PriceData>();
                priceData.Add(PriceData.EX_BEST_OFFERS);
                var priceProjection = new PriceProjection();
                priceProjection.PriceData = priceData;
    
                var args = new Dictionary<string, object>();
                args["marketIds"] = marketIds;
                args["priceProjection"] = priceProjection;
    
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(endPoint);
                req.AutomaticDecompression = DecompressionMethods.GZip;
                req.Timeout = 10000;
                req.ReadWriteTimeout = 10000;
                req.Method = "POST";
                req.Proxy = null;
                req.KeepAlive = true;
                req.ContentType = "application/json";
                req.Accept = "application/json";
                req.Headers.Add("X-Application", m_AppKey);
                req.Headers.Add("X-Authentication", m_SSOID);
    
                StreamWriter sw = new StreamWriter(req.GetRequestStream());
                var call = new JsonRequest { Method = method, Id = 1, Params = args };
                JsonConvert.Export(call, sw);
                sw.Close();
                using (var resp = req.GetResponse())
                {
                    using (var sr = new StreamReader(resp.GetResponseStream()))
                    {
                        result = sr.ReadToEnd();
                    }
                }
    
                return result;
    
            }
            private string RestEndPoint()
            {
                string endPoint = "https://api.betfair.com/exchange/betting/rest/v1.0/listMarketBook/";
                string result = "";
                string postData = "{\"marketIds\":[\"" + m_marketId + "\"],\"priceProjection\":{\"priceData\":[\"EX_BEST_OFFERS\"]}}";
    
                ServicePointManager.Expect100Continue = false;
                ServicePointManager.DefaultConnectionLimit = 200;
                ServicePointManager.MaxServicePointIdleTime = 2000;
    
                if (m_SSOID == null)
                    nonInteractiveLogin();
    
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(endPoint);
                req.AutomaticDecompression = DecompressionMethods.GZip;
                req.Timeout = 10000;
                req.ReadWriteTimeout = 10000;
                req.Method = "POST";
                req.Proxy = null;
                req.KeepAlive = true;
                req.ContentType = "application/json";
                req.Accept = "application/json";
                req.Headers.Add("X-Application", m_AppKey);
                req.Headers.Add("X-Authentication", m_SSOID);
    
                StreamWriter sw = new StreamWriter(req.GetRequestStream());
                sw.Write(postData);
                sw.Close();
                using (var resp = req.GetResponse())
                {
                    using (var sr = new StreamReader(resp.GetResponseStream()))
                    {
                        result = sr.ReadToEnd();
                    }
                }
    
                return result;
            }
    
            public string nonInteractiveLogin()
            {
                textBox1.Text = "";
                string ssoid = String.Empty;
                string[] info;
    
                try
                {
                    string uri = string.Format("https://identitysso.betfair.com/api/login?username={0}&password={1}&login=true&redirectMethod=POST&product=home.betfair.int&url=https://www.betfair.com/", username, password);
    
                    HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(uri);
                    myRequest.Method = "POST";
                    myRequest.Timeout = 5000;
                    WebResponse thePage = myRequest.GetResponse();
                    info = thePage.Headers.GetValues("Set-Cookie");
                    int i = 0;
                    while (ssoid == String.Empty && i < info.Length)
                    {
                        if (info[i].Contains("ssoid="))
                        {
                            ssoid = info[i].Split(new string[] { "ssoid=" }, StringSplitOptions.None)[1].Split(';')[0];
                            m_SSOID = ssoid;
                            textBox1.Text = m_SSOID;
                        }
                        ++i;
                    }
                    if (ssoid.Length == 0)
                    {
                        textBox1.Text = "Login Error";
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine("Message :{0} ", ex.Message);
                }
    
                return ssoid;
            }
    
        }

  • #2
    I would love to be able to run the code and give you a comparison figure, but I am struggling over two final bits.

    1. Where is JsonRequest defined? Do you have the class code for that?
    2. Where is JsonConvert.Export defined? Is this a Newtonsoft call or something different?

    Comment


    • #3
      You need to add a reference to Newtonsoft.Json https://www.nuget.org/packages/Newtonsoft.Json/

      The easiest way is in VS, manage NuGet Packages and search online for json.NET. Below is a the solution folder which is probably quicker than listing all of the classes
      https://www.dropbox.com/s/dogym8i27q...0Copy.rar?dl=0
      Last edited by ozknows; 13-01-2015, 05:57 PM.

      Comment


      • #4
        Thanks - I had added the Newtonsoft library manually but it didn't seem to find the JsonConvert.Export method.

        Anyway, I have loaded your solution file and run it on a PC here (from Debug mode in Visual Studio).

        This gave the following results:

        Button 1 (10 successive clicks from startup):
        00:00:00.7213847
        00:00:00.2489869
        00:00:00.1962594
        00:00:00.1966941
        00:00:00.1896749
        00:00:00.1843710
        00:00:00.1859435
        00:00:00.1942673
        00:00:00.1851175
        00:00:00.1836779

        Button 2 (10 successive clicks from startup):
        00:00:00.6243256
        00:00:00.1857844
        00:00:00.1833836
        00:00:00.1862357
        00:00:00.1822211
        00:00:00.1934885
        00:00:00.1982037
        00:00:00.1925234
        00:00:00.2111716
        00:00:00.1842291

        Tests were run on a PC with a few applications already running (including some making calls to Betfair).

        I'll try again later tonight when I have terminated all current applications.

        Comment


        • #5
          The 2 buttons just give the difference between using REST and JSON but I wanted to compare times on non vendor App key vs vendor app.

          Do you get a difference between using a vendor key and a non vendor key or comaparing your time against a 3rd party app.

          Comment


          • #6
            I will do that test later tonight when I can terminate all other applications.

            Out of interest what is that market, so I can try getting data for it from a 3rd party app?

            Comment


            • #7
              That market in particular is here http://www.betfair.com/exchange/plus...et/1.116868859

              It can be any market though. All of the markets I've tested I still get approx 20ms gap between my code response time and the vendor apps.

              Comment


              • #8
                I have tested your code with a vendor key and a non-vendor key and there appears to be no difference.

                The times are consistent with my previous message.

                I have also looked at the reported times for the market using Gruss Betting Assistant and the time is reported as about 48-53ms.

                Are you sure you are measuring like for like?

                Could it be that Gruss is measuring just the time taken to get the response, whereas you are looking at the time to get and deserialise the response.

                Comment


                • #9
                  No I've moved the timers around the GetResponse code only but it's hardly any difference so just moved them back to cover the full request and response. It's the response that's taking up all of the time.

                  You're seeing a massive difference to Gruss based on your earlier results. If Gruss for you is 48-53 ms response your earlier results are showing approx 180ms response.

                  Comment


                  • #10
                    I'm only going on what Gruss displays - I have no idea if it is accurate.

                    Comment


                    • #11
                      Surely 3 vendors can't all be inaccurate? Also, if you hook up wireshark you can see they really are accurate.

                      Comment


                      • #12
                        I've just tried your code with another app key and it shows about 91ms.

                        I'm off to repeat the tests using the other two keys.

                        [Later]
                        Now all 3 keys give me 91-95ms response times!
                        Last edited by betdynamics; 14-01-2015, 12:44 AM.

                        Comment


                        • #13
                          So you are potentially about 40ms adrift which is a big difference. What codebase do you normally use? Do you get similar response times on that?

                          Comment


                          • #14
                            Added some timing code to my own code (C#/.Net 4.0) and got the same response - 91-95ms.

                            Comment


                            • #15
                              What are your thoughts about that?


                              I know their bet matching engine only updates the prices every 100ms but to be 20ms+ behind vendor response times is not an even playing field.
                              Last edited by ozknows; 14-01-2015, 11:24 AM.

                              Comment

                              Working...
                              X