3

I hope this is the correct site to post this on. I wasn't sure if I should post here or Server Fault, but seeing as this involves the website perspective, I thought perhaps this community might be a little more accurate, but I'm not 100% on that.

I have been banging my head against the wall for over half a year trying to figure out just what's going on here. I would be ecstatic if I could track down why AJAX calls are slow when going through our Site Server.

I have built a small web-app for the organization I work for and it is pretty much set up like this:

enter image description here

The site itself (WebMatrix IIS Express site) resides on the Site Server, but (with the help of C#) it uses SQL queries to query a (considerably large) database on our Database Server.

The problem is that when my site performs the AJAX (simple jQuery $.ajax() calls) that requires it to query the database, the response takes over 5 seconds, each!

(Chrome Network Details): enter image description here

(You'll see that some of the responses are really quick. These responses contain no or a lot less data than the other responses. Maybe there's a data limit somewhere that's causing the Site Server to analyze them?)

Now here's the kicker:

On the Development machine, the local machine the site is developed on, cuts out the Site Server, has the same code, and queries the same database, but the lag doesn't persist in this scenario. The responses in this scenario are in the low millisecond, just what I would expect it to be.

Here's what the Chrome Network Details look like from the development machine:

enter image description here (None even close to 1 second, let alone 5).

Some More Specifics

  • When launching this site straight from the Site Server, the lag persists.
  • WebMatrix uses SQL Server CE, while the SQL Installed on the Database Server is SQL Server 2005 (I really don't think this makes a difference, as the query itself isn't anything special, plus it's the same code that's used in either scenario).
  • The Site Server has been tested to see if the RAM, Processor, and Bandwidth are maxing out, but the truth is that running this web-app doesn't even touch the Site Server's resources. The same has been found for the Database Server, as well.
  • The connection to the database is readonly (doubt this matters, just trying to give as much detail as possible).
  • We have indexed the database on the Database Server, but it helped, virtually, none at all.
  • Even though it is just an Intranet site, I am told that putting the site directly on the Database Server is not an option.
  • At the moment, the AJAX requests are not asynchronous, but it should still not take this long (especially considering that it only lags from the Site Server and not from the Development Machine, even though the code is 100% identical in both cases).
  • Probably doesn't make any difference, but I am in an ASP.NET WebPages using WebMatrix with C# environment.
  • The Operating System on the Site Server is: Windows Server 2008 R2
  • The Operating System on the Database Server is: Windows Server 2003

What could make this app work well from my local machine but not from the Site Server? I think the problem has to be the Site Server, given this, but none of its resources are maxing out or anything. It seems to only lag by about 5 seconds per request if the data being returned is over a certain amount (an amount that seems pretty low, honestly).

Truth is, I am hopelessly stuck here. We have tried everything over the past several months (we are having a similar problem with another Intranet site where the AJAX calls lag there, too, we have just lived with it for a while).

I don't know what else to even look into anymore.

In case anybody wants to see some code

jQuery (one of the AJAX requests, they are all just repeats of this with different parameters)

$.ajax({
    url: '/AJAX Pages/Get_Transactions?dep=1004',
    async: false,
    type: 'GET',
    dataType: "json",
    contentType: "application/json",
    success: function (trans) {
        for (var i = 0; i < trans.length; i++) {
            trans[i][0] = getTimeStamp(trans[i][0]);
        }
        jsonObj1004 = trans;
    },
    error: function (jqXHR, textStatus, error) {
        alert("Oops! It appears there has been an AJAX error. The Transaction chart may not work properly. Please try again, by reloading the page.\n\nError Status: " + textStatus + "\nError: " + error);
    }
});

C# Server Side Code (With Razor)

@{
    Layout = "";

    if (IsAjax)
    {
        var db = Database.Open("OkmulgeeCIC");
        Dictionary<string, double> dataList = new Dictionary<string, double>();
        var date = "";
        var previousDate = "";
        double amount = 0;
        string jsonString = "[";
        string queryDep = "SELECT ba_trans_entered AS transDate, (ba_trans_amount * -1) AS transAmount FROM BA_VTRANS WHERE ba_trans_year >= 2011 AND ba_trans_operator = 'E' AND ba_trans_system = 'AP' AND ba_trans_ledger LIKE @0 + '%' ORDER BY ba_trans_entered ASC";
        string dep = Request.QueryString["dep"];

        foreach (var row in db.Query(queryDep, dep))
        {
            date = row.transDate.ToString();
            date = date.Substring(0, date.IndexOf(" "));
            amount = Convert.ToDouble(row.transAmount);

            if (date == previousDate)
            {
                dataList[date] = dataList[date] + amount;
            }
            else
            {
                dataList.Add(date, amount);
            }

            previousDate = date;
        }

        foreach (var item in dataList)
        {
            jsonString += "[";
            jsonString += Json.Encode(item.Key) + ", ";
            jsonString += Json.Encode(item.Value) + "],";
        }

        //jsonString += Json.Encode(date);
        jsonString = jsonString.TrimEnd(',');
        jsonString += "]";
@Html.Raw(jsonString)
    }
    else
    {
        Context.RedirectLocal("~/");
    }
}

ADDITONAL INFO FROM SQL SERVER PROFILER

From Development Machine enter image description here

From User Machine (lag) enter image description here

VoidKing
  • 6,282
  • 9
  • 49
  • 81
  • Could this be related to security? When a user accesses the website and indirectly the database, is there some kind of translation going on towards the login used in the connectionstring ? Also, if you'd look at it from the SQL-Profiler (SQLStmtCompleted event), is the duration field there different when comparing it being launched by the DEV-machines vs being launched by the webserver? – deroby Mar 20 '14 at 11:03
  • @deroby As soon as I get a chance I will let you know. – VoidKing Mar 20 '14 at 13:24
  • @deroby I have added two screenshots (of the SQL Server Profiler) comparing both the development machine requests and the user machine requests. Let me know if you have any questions. – VoidKing Mar 20 '14 at 14:40
  • What's interesting to see from these traces is that the actual queries (`exec sp_executesql etc`) really don't take any time at all, but the Logout event shows a duration of 5s in case of the second screenshot while this is only milliseconds in the first one. Could you redo the trace and make sure the startTime is fully shown? Also, could you add the 'EventSubClass' event to the list of columns for Login/Logout? I'm thinking this could be connection-pooling related. ['required' columns : EventClass, TextData, Duration, SPID, StartTime, EndTime, EventSubClass] – deroby Mar 24 '14 at 09:42
  • These profiler shots have the same requests?? Some of the reads and cpu usage are substantially less. Anyway, the high duration fields are from audit logouts which is how long the connection was maintained for. Tells me the issue is not on your database. If its the same code base, I couldnt image the application spinning its wheels. What connectivity tests have you performed from App server to DB? – Ricky Hartmann Mar 24 '14 at 21:36
  • Have you checked to see what route the data literally takes across the network in each case? I'm not a network person, but do know that in rare cases the data can get sent through the network the long way around. That happened to us once. I think they used a tool called BlackBox to find it, but that was a long time ago. – Ramoth Mar 25 '14 at 00:38
  • Could you repeat the Chrome devtools runs and include the Timeline data when the mouse is over the indicator? As in when it shows the details of the timing: Blocking, DNS Lookup, Connecting, Sending, Waiting, Receiving. I would guess the all the difference is in the Waiting, but if it is somewhere else that could help with the answer. – peterfoldi Mar 25 '14 at 19:30

5 Answers5

1

Just looking over your code two things jumped out for me

1) You're not closing your db connection, this is very bad. Either wrap your connection object in a using block (preferred) or add a call to .Close() at the end of your data work

using(var db = Database.Open())
{
     //do work
}

2) Doing string concatenation in a loop like that is a terrible thing to do and very slow. Either use a StringBuilder. Or since you're outputting JSON anyway just bundle your objects into a list or something and pass that to JSON.Encode() (preferred)

Dave
  • 498
  • 2
  • 7
  • 22
iamkrillin
  • 6,798
  • 1
  • 24
  • 51
  • Are you sure this is something that needs to be done in the WebMatrix WebPages environment? It just seems funny that none of the tutorials and even the examples on Mike Brind's site never mention the need to do this. – VoidKing Mar 26 '14 at 13:14
  • Well, thank you for the info, but, while I'm sure this is good advice, and I do appreciate it, it is not solving the issue. – VoidKing Mar 26 '14 at 13:31
  • Also, the problem with **2)** is that it returns an object with multiple properties when I use `Json.Encode()`, instead of an array of arrays (which is what HighStock expects for use with its graphs, apparently). – VoidKing Mar 26 '14 at 13:45
0

It seem to me this problem come from your Site Server but anyway you can try this: 1/ Publish your site to any Internet web server. if it is still slow => your code problem -> Check your code. If not go to 2/ Check your configuration Site Server and Database Server. It might be Firewall or TCP/IP:Port or NETBIOS/Domain name between two Server.

Minh
  • 341
  • 4
  • 12
0

I do not know if this has any relevance to this problem because i cannot see how you are calling your application. But I have multiple times experienced about 5 sec lag on IIS using C# when i use domain names to call other servers (this can also be localhost). Instead the ip should be used.

It could be nice if you tried playing around with this using IP instead of using a domain

Mibsen
  • 91
  • 4
  • Where at? Do you mean the connection string to the database? If so, I am using IP. Is that what you mean? – VoidKing Mar 26 '14 at 13:56
  • Here is my connection string (if that's even what you're talking about) ` ` – VoidKing Mar 26 '14 at 14:00
  • I want to try your solution, but I don't know what to do that I'm not already doing... – VoidKing Mar 26 '14 at 15:55
  • Sry for the late response. I can see you use the correct connection String with ip, so the problem is not here. When you are connecting from the user machine (with lag) is this on the same network as the development machine? – Mibsen Mar 27 '14 at 09:42
  • Are you hitting the Site Server using a domain from the user machine? Please try using the Ip address to the site server instead. By looking down the comments and the main issue the problems is in the Site server. I think it is a setup issue in the IIS, firewall or dns. – Mibsen Mar 27 '14 at 15:14
  • Well it's kind of odd, but I can't seem to connect to it using just the ip address. I do this: "http://20.101.100.31:2817" and get nothing. I know the address and port are right, but I just get resource not found messages... ? – VoidKing Mar 27 '14 at 18:47
  • If you use port 2817 to access your application i think the problem is the firewall. Try disable all firewall on your server and see if it works. maybe you should try deploy your application in iis7-8 instead and set it as the default application on localhost. – Mibsen Mar 27 '14 at 19:23
  • Disable the firewall for the Site Server or the Database Server? I'm assuming you mean the Site Server, because the port number is in regards to that machine? – VoidKing Mar 31 '14 at 13:28
  • Yes the Site server. It sounds like Your database server Works as it should. – Mibsen Apr 01 '14 at 18:33
0

I had something similar when working with AjAX and JSF site.

Jquery loading taking excessive time

Since you already have it working from dev machine, it might not be a problem in your case. But to rule out any such scenario, can you develop the page without using jquery ?

Community
  • 1
  • 1
vsingh
  • 6,365
  • 3
  • 53
  • 57
0

I had a similar issue where I would call 20 sprocs using a for loop, they were not large sprocs mind you but a sproc that would return 5 values.

It would work fine but time to time it would almost like lag out and would not be able to load any of the sprocs or a very small amount until timing out completely.

That is when I discovered Parameter Sniffing for SQL Server.

To fix it I added in sproc Parameters equal to the incoming parameters from my C# code.

OLD CODE:

CREATE PROC [dbo].[sp_procname_proc]
(
   @param1 int,
   @param2 int,
   @param3 varchar(5),
   --..... etc .....
)AS
BEGIN
  -- select from db
END

NEW CODE

CREATE PROC [dbo].[sp_procname_proc]
(
   @param1 int,
   @param2 int,
   @param3 varchar(5),
   --..... etc .....
)AS
BEGIN
  @localParam1 INT = @param1
  @localParam2 INT = @param2
  @localParam3 varchar(5) = @param3
  -- select from db using new parameters
END
imBlue
  • 114
  • 1
  • 11