Developing an app that uses data synchronization. Sending images (even resized) takes time if it's done over slow internet connection. Thinking, it would be best first to check internet speed, and sent data only if the speed is acceptable. There's Apple Reachability class but it only has method for checking wifi is on. I guess for me, it would be enough to ping a host and grab delay information out of the ping cmd result. That delay info I would use for deciding is it worth to send data now or to wait.
Reachability or ping won't tell you how fast or slow the file will be transmitted. That is a function of ping_time + (file_size / bandwidth). For any large file, the ping_time is much smaller than file_size/bandwidth.
The easiest way to measure this is for the app to download and upload a not-too-small-not-too-large file and decide if in fact the upload and download speeds are "fast enough".
Doing this is fairly involved, however Apple has a complete working example program here:
https://developer.apple.com/library/mac/#samplecode/SimplePing/Introduction/Intro.html#//apple_ref/doc/uid/DTS10000716-Intro-DontLinkElementID_2
Related
I'm using an ESP8266 with ESP8266WiFi and ESP8266HTTPClient libraries. My app doesn't have enough memory to download the entire JSON file that I need, but all I really need is a few fields from it, so I can discard most of it as I read it in.
What I don't understand is how to start, stop, or otherwise slow down the incoming data so that I can process it and pick out what I need as it comes in from the server. I have to use a fairly small buffer when I make the connection due to memory limitations caused by the rest of the program.
Is there a way to fill the buffer from the server, pause the transmission, process and clear the data in the buffer, and then resume the transmission until the whole JSON file is processed?
Sounds like you will want to use a streaming JSON parser. There are a couple of forks of such a library on GitHub. https://github.com/mrfaptastic/json-streaming-parser2 seems to be the one still maintained.
Been banging our heads on this for two weeks now. Any help will be greatly appreciated.
Problem:
I am using NSURLConnection to fetch JSON data from a RESTfull Web service, the requirement is such that I can't do lazy loading of data. It is one big chunk of data that needs to be processed on the 1st screen of the app every time the logged in user opens the app. I know its not a smart thing to do, but can't help it. The caching is being done in the local Sqlite DB. We are using Async NSURLConnection that is giving us a constant 3-4 sec hit on the performance.
We tried Sync NSURLConnection and figured out the Async NSURLConnection is taking around 3-4 sec extra to process the same request. But Sync NSURLConnection is not reliable at all, it fails to get the complete JSON more than half of the times. And the combination of Sync NSURLConnection with NSOperation will not help.
We tried making the call in a separate app just to observe the performance for that one particular request, and still got the same results.
So, currently we are getting an average execution time of the complete request to be around 6-8 sec. Which we feel I quite high for your first screen of the app. (please let me know if its not much, it feels like bad user experience to me).
Questions:
Isn't NSURLConnection the standard way for doing a request like this?
Is there a better and faster (reliable) way of doing this apart from NSURLConnection?
Can I optimize the performance of NSURLConnection? If yes, please point me to the right direction.
Has anyone tried CFHTTPStream? If yes, then is it better than NSURLConenction in terms of performance?
Thanks
#GoZoner Thanks a ton for the response. We tested in the below three ways
Since it is the 1st screen of the app, so there is no real case of the app doing anything else, still the results were different and a consistent 3-4 sec loss with Async.
We made a raw call in a separate test app, which did nothing but just that one web service call and still the results were same.
We tested on the device and on the simulator. On the device, as expected the results were worse, around 4 secs constant lag in an Async NSURLConnection call.
We were also surprised with the reliability issue as it makes very little sense that a Sync NSURLConnection is unreliable. But after running the tests a zillionth time we realized that it is actually not reliable, not because of something in the NSURLConnection library, but because the 3G or Wi-fi connections are not reliable so the call use to break mostly due to the connection(my assumption). This particular problem is handled beautifully by Async NSURLConnection since it keeps calling and appending data till the data received is complete.(This can sometimes take more than 10-12 attempts to append the data to complete the JSON). Since the Sync NSURLConenction is making only one attempt in getting the data, it fails miserably in the unreliable mobile network connectivity.
#Andrea Thanks for the response :) Will surely give YAJL a spin. But i believe that the problem is more with the connection rather than the parsing of the JSON, I may be wrong. Does YAJL have a reliable connection handling mechanism?
Looking forward to more responses, your suggestions and comments are actually very valuable :)
Thanks
try to use ASIHttpRequest the response time may be faster than the NSURLConnection.
I would like to check used bandwidth when playing a video with MPMoviePlayerController to be able to play a video which matched client bandwidth.
For now, I download a part of my file by using NSURLConnection and I can find bandwidth. But I think it's not a good idea to download more data than expected (and the goal is to use as less bandwidth as possible).
Does a 'current downloaded bytes' property, or something like that, exist ? I hope you can help me.
Thanks a lot !
Take a look at the Reachability sample code, it will help you determine if the client is on WiFi,WWAN (3G/Edge), etc. You can make certain assumptions based on these findings. If you want exact speed, you'll download a file and check the speed.
You may want to look into HTTP video streaming, you can provide different (varying level of quality) versions of the video for each connection speed. The server determines the version to send.
Some docs on HTTP Streaming:
http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/Introduction/Introduction.html
http://www.scribd.com/doc/20173481/iPhone-Streaming
I have looked at several variations on the Reachability example such as the Donoho change and erica saduns UIApplication extension, but none of these allow you to determine the quality of your 3g connection.
Is there a programatic way to see signal strength and link quality?
I think you need to decide exactly what you mean by quality and also understand that it constantly changes.
The only really accurate measure is unfortunately historical - i.e. you can do a download or upload test and measure the time it took and any packet loss, jitter, delay etc and this will let you know what the quality was when your test was run.
The reason I say it is historical is that this does not guarantee that it will stay like this for any given time - for example you may move between cells (or rooms in the case of WiFi), or several other users in your area may start utilizing the bandwidth heavily.
It may be that a simple download or upload test is sufficient for your purposes to (I am guessing...) decide if your want to run your application in a certain way, and then you can build in further checks into the application itself to see if you need to adapt to a change in the network (e.g. you could trigger on the time for a particular application message transaction to complete)
Right now I'm trying to make a mmorpg for the iPhone. I have it set up so that the iPhone requests for the player positions several times a second. How it does this is that the client sends a request using asynchronous NSURLConnection to a php page that loads the positions from a mysql database and returns it in json. However, it takes about .5 seconds from when the positions are requested to when they actually get loaded. This seems really high, are there any obvious things that could cause this?
Also, this causes the player movement on the client to be really choppy too. Are there any algorithms or ways to reduce the choppiness of the player movement?
Start measuring how long the database query takes when you run it outside your iPhone.
Then measure how long it takes when you send the same http request from something other than your iPhone(It's e.g. a 10-15 line c# program to figure this out).
If none of the above show any sort of significant latency, the improvements need to be done on the iPhone side. Some things to look out for:
GPRS/3G has rather high latency
GPRS/3G has rather high bit error rates - meaning there's going to be quite a few dropped packets now and then which will cause tcp to retransmit and you'll experience even higher latency
HTTP has a lot of overhead.
JSON adds a lot of overhead.
Maybe you'll need to come up with a compact binary format for your messages, and drop HTTP in favor of a custom protocol - maybe even revert to UDP
The above points generally don't apply, but they do if you need to provide a smooth experience over high latency,low bandwidt, flaky connections.
At the very least, make sure you're not setting up a new TCP connection for every request. You need to use http keep-alive.
I don't have any specific info on player movement algorithms, but what is often used is some sort of movement prediction.
You know the direction the player is moving, you can derive the speed if it's not always constant - this means you can interpolate over time and guess his new position, adjust the on screen position while you're querying for the actual position, and adjust back to the actual position when you get the query response.
The trick is to always interpolate over time within certain boundaries. If your prediction was a bit off compared to what the query returned, don't immediatly snap the positon back to the real position. Do interpolation between the current position and the desired postion over a handful of frames.
On the server side you should be using some system that keep running and that keeps the database connection open all the time. Preferably it would also cache things instead of requesting them from database all the time.
Also, do not make a new HTTP request for every update. It would be best if you hadn't need to use HTTP at all, as it really isn't suitable for realtime comminunication.
GPRS typically has 600 ms ping time, 3G has 300 ms and HSPA has 100 ms. See which mode is being used. Notice that some devices (I don't know of iPhone) drop from HSPA to regular 3G for power-saving reasons whenever there is not enough traffic to justify the faster mode.
As for position, a rather common practice is to apply a linear prediction, i.e. make the character continue movement in current direction, at the current speed, even when no data from server is available yet.
Most importantly: benchmark/profile to see where the latencies are. Is it your server, the network connection or the application.
Loading the player positions that fast has downsides.
It hammers your server.
3G isn't really meant to support low-latency applications
So I don't see a mmorpg working without some necessary shortcuts at this time, e.g. extrapolating paths based on their velocity and position. Loading positions will not work as fast as you want, especially with a server based on PHP of all things.
Either way, when developing for a mobile platform you're going to have to make sacrifices in terms of features versus a fully-featured desktop implementation.
I might also reimplement some of the more critical stuff if not the whole server in a faster language, e.g. C++.