I have an ASP.NET Web API that exposes all the verbs - the methods are basically empty.
To run the project, you can do this: spin up a new asp.net web project from VS 2017 - then choose Web API. Once the project is created, do a clean and then rebuild. Open up "ValuesController", put a break point inside the PUT method, and run your project.
Here are the code for the API (controller code - I added a line in PUT method):
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
var x = "value: " + value;
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
I do not get the same problem or time difference (or they are very negligible) for other HTTP methods (GET, POST, DELETE).
GET timing data:
POST timing data:
DELETE timing data:
PUT timing data via IE:
Now - here is PUT timing data via CHROME:
I also have tried putting my API on a server - so calling the API would be a call to http://test-server-01/api/values/1 etc - but the same issue for PUT persist.
My question: Can anybody explain what is going on? Why is the call for PUT so slow compared to other VERBS? This only happens in Chrome too - I tried making the same calls in IE, resulting in much faster performance.
[UPDATED]
I did some timing gathering using Chrome Dev Tools and I noticed that most of th delay are happening on Slow Time to First Byte (TTFB). Here is a screen shot of one of my timing data:
[UPDATED MORE]
Here are some more timing data between IE vs Chrome without Fiddler. Timing is captured using respective developer tools.
The timing above is pretty much the average of multiple PUT calls in IE and in Chrome. Chrome always ~8 seconds and IE is about ~4 seconds.
As comparison, issuing a POST in IE and Chrome are resulting in negligible difference between them - they all resulting around ~20ms to ~50ms (although Chrome is almost always faster).
Making a DELETE call also similar to POST in result, ranging ~10ms to ~18ms (Chrome is almost always faster).
[UPDATE MORE MORE]
I tried creating an MCVE - but I cannot duplicate the issue on a different machine. I put the solution on a different laptop, run it using VS 2017, hit localhost via Chrome - no delay/poor performance calling PUT. The timing data that I gathered is on par or similar to POST or DELETE.
So it seems this problem is probably isolated to my work machine. Could it be network issue? Proxy? But if it is the case - should not all calls, including POST or DELETE or GET be delayed or getting poor performance as well? Or why is IE performing better for PUT - if the issue is related to network/proxy?
[UPDATE MORE MORE MORE]
I ran the PUT call via curl using bash - very fast, no delay whatsoever from the same machine that gave me 8 seconds with CHROME.
Related
I recently ran into an instance where I wanted to hit the database from a Task I have running periodically within a web application. I refactored the code to use the ThreadStaticSessionContext so that I could get a session without an HttpContext. This works fine for reads, but when I try to flush an update from the Task, I get the "Index was out of range. Must be non-negative and less than the size of the collection." error. Normally what I see for this error has to do with using a column name twice in the mapping, but that doesn't seem to be the issue here, as I'm able to update that table if the session is associated with a request (and I looked and I'm not seeing any duplicates). It's only when the Task tries to flush that I get the exception.
Does anyone know why it would work fine from a request, but not from a call from a Task?
Could it be because the Task is asynchronous?
Call Stack:
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.System.Collections.IList.get_Item(Int32 index)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
Session Generation:
internal static ISession CurrentSession {
get {
if(HasSession) return Initializer.SessionFactory.GetCurrentSession();
ISession session = Initializer.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
return session;
}
}
private static bool HasSession {
get { return CurrentSessionContext.HasBind(Initializer.SessionFactory); }
}
Task that I want to access the database from:
_maid = Task.Factory.StartNew(async () => {
while(true) {
if(CleaningSession != null) CleaningSession(Instance, new CleaningSessionEventArgs { Session = UnitOfWorkProvider.CurrentSession });
UnitOfWorkProvider.TransactionManager.Commit();
await Task.Delay(AppSettings.TempPollingInterval, _paycheck.Token);
}
//I know this function never returns, I'm using the cancellation token for that
// ReSharper disable once FunctionNeverReturns
}, _paycheck.Token);
_maid.GetAwaiter().OnCompleted(() => _maid.Dispose());
Edit: Quick clarification about some of the types above. CleaningSession is an event that is fired to run the various things that need to be done, and _paycheck is the CancellationTokenSource for the Task.
Edit 2: Oh yeah, and this is using NHibernate version 4.0.0.4000
Edit 3: I have since attempted this using a Timer, with the same results.
Edit 4: From what I can see of the source, it's doing a foreach loop on an IList. Questions pertaining to an IndexOutOfRangeException in a foreach loop tend to suggest a concurrency issue. I still don't see how that would be an issue, unless I misunderstand the purpose of ThreadStaticSessionContext.
Edit 5: I thought it might be because of requests bouncing around between threads, so I tried creating a new SessionContext that combines the logic of the WebSessionContext and ThreadStaticSessionContext. Still getting the issue, though...
Edit 6: It seems this has something to do with a listener I have set up to update some audit fields on entities just before they're saved. If I don't run it, the commit occurs properly. Would it be better to do this through an event than OnPreInsert, or use an interceptor instead?
After muddling through, I found out exactly where the problem was. Basically, there was a query that was run to load the current user record called from inside of the PreUpdate event in my listener.
I came across two solutions to this. I could cache the user in memory, avoiding the query, but having possibly stale data (not that anything other than the id matters here). Alternatively, I could open a temporary stateless session and use that to look up the user in question.
I have a Play 2.1 Java webservice, that calls another webservice.
My service serves JSON made with transforming the XML response of the other webservice.
Initially , I was using a Jersey-Client lib to call my second service.
As this is a blocking call, I've modified the setting to allow 500 threads in parrallel.
I had good results with it , I made a gatling test and it was quite fast (32 seconds to handle 10 000 requests on a distant server).
Then I'ved decided to use only asynchronous calls to optimize the I/O.
Now I use play.libs.WS client instead of the jersey blocking client with the default thread pool parameters.
I use promises to get my results but the rest of my code is exactly the same as before.
Strangely, the performances with my gatling test (just a loop that sends some http GET requests) has dropped and is more than 10x slower...
I've tried to increase the number of threads for the "default-dispatcher" but it's not better.
Could it be because a single thread processes the XML and Json transformations after the WS call ?
The app is structured as following :
//controller :
Promise<Response> = myService.remoteEntities();
return async(promise.map(new Function<Response, Result>() {
public Result apply(Response response) {
List<Entity> entities = // ... XPATH and DOM parsing
return ok(jsonp(callback, toJson(entities)));
}
});
myService.remoteEntities is defined like that :
public Promise<List<Entity>> myServiceMethod {
return WS.url(url.toString())
}
Note : myService is a spring service singleton, and my routes/controllers use spring with the '#'notation
I 've put this in a separated class to be able to use mocks for my tests
Thanks,
Loïc
Note: I've initially posted my problem here : https://groups.google.com/forum/?fromgroups=#!topic/play-framework/SDpPA6UPyFQ
The localeCompare() function does not behave the same in a Firefox extension main code and in a web worker (or chrome worker).
For instance, in the main code, I have this code:
var array = ["École", "Frère", "frère", "école"];
array.sort(function(a, b) {
return a.localeCompare(b);
});
console.log('Main: ' + array);
it shows:
Main: �cole,�cole,Fr�re,fr�re
Which is the right sorting (the encoding is not my problem).
In the worker, I have this code:
var array = ["École", "Frère", "frère", "école"];
array.sort(function(a, b) {
return a.localeCompare(b);
});
self.postMessage(array);
it prints:
Frère,frère,école,�0cole
which is in the wrong order (once again, the encoding is not my problem).
The sorting in the main code is ok, but not the one in the web worker.
I tried to change the options of the localeCompare() function in the web worker, but it does not change anything.
Why is the sorting different in the web worker and how to get it right in the web worker?
(For some reason, I could not send the data to the main code, do the sorting and send it back to the web worker. I still got the wrong order (gives me école,�0cole,Frère,frère).)
Thanks for your help.
localeCompare is still broken in Firefox Web Workers.
Wladimir mentioned Bug 616841, which indeed fixed it almost everywhere... except for web workers, which were left broken because the Intl backend was (is?) not thread-safe, or some other thread-safety issues. The corresponding "Dead end" patch was never reviewed nor checked in.
I now filed Bug 903780, with a test case based on your code, so that localeCompare hopefully will be fixed in the future.
I have an express app running with Sequelize.js as an ORM. My express app receives requests from my main Rails app, and because of the cross-domain policy, these requests are performed with getJSON.
On the client, the request is fired when the user hits a key.
Everything goes fine and express logs the queries being performed (and json being served) each time the user hits the key. Even trying to hit quickly it performs ok. But, whenever I leave the key pressed (or maybe several clients hitting the key very quickly), as it starts firing lots of requests, at some moment the server just hangs, all the requests from that point on are left pending (I see that in the Network tab of Chrome Dev Tools), and they slowly start to timeout. I have to reboot the server to make it respond again.
The server code for my request is:
models.Comment.findAllPublic(req.params.pId, req.params.sId, function(comments){
var json = comments.map(function(comment){
var com = {};
['user_id','user_avatar', 'user_slug', 'user_name', 'created_at', 'text', 'private', 'is_speaker_note'].forEach(function(key){
com[key]=comment[key];
});
return com;
});
res.json({comments: json});
});
And the findAllPublic method from the Comment model (this is a Sequelize model) is:
findAllPublicAndMyNotes: function(current_user, presentationId, slideId, cb){
db.query("SELECT * FROM `comments` WHERE commentable_type='Slide' AND commentable_id=(SELECT id from `slides` where `order_in_presentation`="+slideId+" AND `presentation_id`="+presentationId+") AND (`private` IS FALSE OR (`private` IS TRUE AND `user_id`="+current_user+" AND `is_speaker_note` IS FALSE))",self.Comment).on('success', cb).on('failure',function(err){console.log(err);});
}
How to avoid the server from getting stuck? Am I leaving some blocking code in the request that may slowly hang the server as new requests are made?
At first I thought it could be a problem because of the "forEach" when composing the json object from the Sequelize model, but I also tried leaving the callback for the mysql query empty, just responding empty json and it also got frozen.
Maybe it is a problem of the mysql connector? When the server gets stuck I can normally run the mysql console and perform queries on my database and it also responds, so I don't know if that's the problem.
I know I could just control the key event to prevent it from firing too many requests when the key gets pressed for a long time, but the problem seems to appear also when several clients hit the key repeatedly and concurrently.
Any thoughts? Thanks in advance for the help :D
Two things:
It seems like you have some path where res.render is not being called. It could be that the database you're connecting to is dropping the connection to your Express server after the absurd number of requests and the callback is never fired (and there's no database.on('close', function() { // Handle disconnect from DB, perhaps auto-restarting }) code to catch it.
Your client-side code should detect when an AJAX request on keypress is still pending while a new one is being started, and cancel the old one. I'm guessing getJSON is a jQuery method? Assuming it's jQuery's, then you need something like the following
.
var currKeyRequest = null;
function callOnKeyUp() {
var searchText = $('#myInputBox').value;
if(currKeyRequest) {
currKeyRequest.reject();
currKeyRequest = null;
}
currKeyRequest = $.getJSON('path/to/server', function(json) {
currKeyRequest = null;
// Use JSON code
});
}
This way, you reduce the load on the client, the latency of the autocomplete functionality (but why not use the jQuery UI autocomplete if that's what you're after?), and you can save the server from some of the load as well if the keypresses are faster than handshaking with the server (possible with a good touch-typist a few hours flight away).
Using Windows 2008, C#, Firefox 3.5.1, Selenium RC (v1.0.1)
When it works, this code executes very quickly and the page loads within .5 seconds.
However, the session always seems to fail after 3 - 5 iterations. The open command will cause a window to be spawned, but no page to be loaded. Eventually a timeout exception is returned. The page has not actually timed out. Instead, it is as though the request for a URL has never reached the browser window.
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
var s = new DefaultSelenium("localhost", 4444, "firefox", "http://my.server");
s.Start();
s.SetSpeed("300");
s.Open("/");
s.WaitForPageToLoad("30000");
s.Type("//input[contains(#id, '_username')]", "my.test");
s.Type("//input[contains(#id, '_password')]", "password");
s.Stop();
}
}
}
I have a similar set up (Firefox 3.6.15, Selenium RC 1.0.1, but on WinXP and using the Python libraries) and I am working with a couple of sites - one site is naturally prone to timeouts in normal use (e.g. by a human user) whereas the others typically are not. Those that aren't appear a little slower but the one that is prone to timeouts is significantly slower when run via RC than by a person - it won't always timeout but the incidence is much much more common.
My limited mental model for this is that somehow the extra steps RC is doing (communicating with the browser, checking what it sees in the returned pages etc etc) are somehow adding a bit to each step of the page loads and then at some point they will push it over the edge. Obviously this is overly simplified, I just haven't had time to properly investigate.
Also, I do tend to notice that the problem gets worse over time, which fits a little with what the OP has seen (i.e. working the first time but not after 3 - 5 attempts). Often a reboot seems to fix the issues, but without proper investigation I can't tell why this helps, perhaps it is somehow freeing up memory (the machine is used for other things), getting allocated to a different one of our company's proxies or something else I haven't considered.
So... not much of a full answer here (a comment would have been more appropriate, but my login isn't able to yet), but at least it reinforces that you're not the only one. Periodic restarts are an annoying thing to need to do, but in the absence of any smarter analysis and answers, maybe they'd be worth a shot?
I was facing the same problem .This is because open method of DefaultSelenium has timeout of 30000ms, so it waits for 30s for your page to load. You can try this trivial solution.
//selenium is DefaultSelenium instance as private member of the class
boolean serverStartTry = false;
int tryCount =1;
while((!serverStartTry) && tryCount <= Constants.maxServerTries){
try{
this.selenium.open(ReadConFile.readcoFile("pageName"));
System.out.println("Server started in try no: "+tryCount);
serverStartTry =true;
}catch (SeleniumException e) {
System.out.println("Server start try no: "+tryCount );
System.out.println("Server Start Try: "+ serverStartTry);
serverStartTry = false;
tryCount++;
}
}
if(!serverStartTry){
System.out.println("Server Not started, no. of attempts made: "+tryCount);
System.exit(0);
}
I've solved using:
selenium.setTimeout("60000");
before open instruction.