Confused about making batch call when building Restful API.
For example, I want to check 100 students height. What's the difference among:
1) check height one by one
2) check height with a batch of 20
3) check height with a batch of 50
What's the benefit of it? I know batching will decrease HTTP requests amount. Will this count much when we evaluate the speed of an API?
How to choose the batch size?
I think you could have found this with a bit of googling - but I'll answer here all the same.
The benefits of batching generally depends on what you do with it.
If you have a keep-alive connection, you have no overhead of handshaking, and then you don't spend too much time dealing with subsequent packets along this connection. You can then pipeline requests and decrease your latency. However, in HTTP1.1, requests are still FIFO - so you have to 'handshake' each and every one. This is where you can leverage the power of batching!
Because you can send/retrieve all the data you need for all requests hereafter, you can minimize the overheads incurred from setting up each individual HTTP connection. This does mean that you will have to wait a bit longer to handle the request as everything is packed into one request, but your throughput improves. The reason for this is the roundtrip from making first request to receiving final response is not multiplied by the number of requests you have to make.
Something to keep in mind, however, is TTFB - time to first byte. If you load data progressively, it can be perceived as faster by a user. Imagine a website which loads one of each one thousand resources at a time, and you as a user can see these popping up, versus a website that loads all one thousand at once, and you just see a spinner until all the resources have been loaded? I'll bet you find the progressive loading scheme "looks" faster.
Naturally, batching very much depends on what you're doing with the requests, if it is to be worthwhile.
Sometimes, you have to be careful with batching, as you can put a lot of load on a server if you have multiple users concurrently making batch requests, and it might be a better balancing scheme to process requests sequentially. Of course, you will be able to figure this out with a bit of monitoring and analytics.
Related
For a desktop App (ERP like functionality) I'm and wondering what would be wiser to do.
Assuming that both machines are equal in performance and the server has to deal with max. 5-10 clients and no other obligations. Is it better to load all data initially (~20.000 objects) and do filtering, sorting etc. on the client (electron) or is it better to do the processing on the backend (golang + postgres) over Axios. The user interface should be as snappy as possible but also get the data as fast as possible.
A costly operation is filtering 15.000 Objects by a reference ID. (e.g. a client can have several orders)
So objects that belong to a "parent object" are displayed by querying all those objects by a parentID.
Is there a general answer to what would be more performant, or a better choice here? Doing some assumptions, like a latency of 5ms in the network + 20ms for the API + a couple for filling the store.
At which data size will this operation be slower on the frontend or completely unsustainable?
If it's not a performance problem, are there other reasons I would want to do this on the server?
Edit: Client and Server are on the same local network
You specifically mention an ERP-like software. For such software you have to carefully consider the value of consistency:
Will your software need to show the same data for all clients?
If the answer to this is yes, then the simplest implementation is to do data processing on the server which informs all clients of changing data.
If the answer to this is no, then you should be fine doing most processing on the client software.
There are of course ways to do most of your processing on the client yet still have consistency but they will add complexity to your overall design. One implementation is to broadcast changes on one client to all other clients. This is the architecture behind most multiplayer online games.
Another way to tackle this is implemented by git: the data on all clients are different from each other but there are ways to synchronize each client data with the server thus achieving eventual consistency.
Another consideration you have to think about is the size of your data:
Will downloading all the data from the server take more than a few seconds?
If downloading all data from the server takes too long then the UI will be essentially unresponsive when starting.
Let's say you've got a fully hypermedia driven API. Consumers have to navigate three reources, via following hypermedia, until they can get to the resource they want. Is there any reason a client could not cache these steps temporarily and go directly to the resource they want?
I know the goal of REST is to decouple clients and servers, but if you've got 5 web requests going on behind the scenes the user experience could be poor waiting for all this to happen.
The worst case I can think of is that a cached URL gets changed. And so the client will just start from the entrypoint again and cache the steps.
Caching on the client side is going to be very important for a lot of well performing Hypermedia clients. Here is some more specific guidance straight from Fielding's dissertation:
The advantage of adding cache constraints is that they have the potential to partially or completely eliminate some interactions, improving efficiency, scalability, and user-perceived performance by reducing the average latency of a series of interactions. The trade-off, however, is that a cache can decrease reliability if stale data within the cache differs significantly from the data that would have been obtained had the request been sent directly to the server.
The are trade offs but event a short time frame for caching will greatly improve performance. Ideally the Hypermedia API will provide caching guidance. This could be done in the same manner that HTML caching works with the browser and Expires and Cache-Control headers.
Also if the resource has moved then the API should inform you with the proper 301 Moved Permanently response.
I want to know how much of the battery is drained if I do x number of HTTP requests.
In other words, if I want to let the iPhone battery be drained by 10%, how many HTTP request would I have to make?
Just to make it clear how I want to approach this calculation, it is perfect if the power usage during the handling of the response is not counted. If it is counted the answer would vary depending on the response length, making it a subjective and scenario-driven answer.
The goal is to let a developer optimize how many HTTP requests are justified, but they can only do this if they know the numbers.
The short answer would be "don't do more http requests than needed".
The longer answer is that there is no such thing as a "standard" http request. You will need to measure the impact yourself with a defined set of requests/responses. Besides battery drainage you also need consider the justification for putting a heavy load on the users bandwidth. Some users are charged a lot of money for data transfer over e.g. 3G.
A lot of things can influence the metrics, including length of response, latency, bundling of connections, signal strength of carrier network, etc, etc, etc....
There is no way to give a hard number for this as the result will vary depending on numerous conditions including the network conditions, physical conditions of the phone and battery, what apps are running in the background, etc.
The only way to get any kind of idea of this is to write an app that makes continuous HTTP request and measure the battery drain. Even that won't give you a real answer because of all of the variables.
The true answer, of course, if that if an http request is absolutely needed, then it is justified.
Uploads from my app are too slow, and I'd like to gather some real data as to where the time is being spent.
By way of example, here are a few stages a request goes through:
Initial radio connection (significant source of latency in EDGE)
DNS lookup (if not cached)
SSL/TLS handshake.
HTTP request upload, including data.
Server processing time.
HTTP response download.
I can address most of these (e.g. by powering up the radio earlier via a dummy request, establishing a dummy HTTP 1.1 connection, etc.), but I'd like to know which ones are actually contributing to network slowness, on actual devices, with my actual data, using actual cell towers.
If I were using WiFi, I could track a bunch of these with Wireshark and some synchronized clocks, but I need cellular data.
Is there any good way to get this detailed breakdown, short of having to (gak!) use very low level socket functions to reproduce my vanilla http request?
Ok, the method I would use is not easy, but it does work. Maybe you're already tried this, but bear with me.
I get a time-stamped log of the sending time of each message, the time each message is received, and the time it is acted upon. If this involves multiple processes or threads, I have each one generate a log, and then merge them into a common timeline.
Then I plot out the timeline. (A tool would be nice, but I did it by hand.)
What I look for is things like 1) messages re-transmitted due to timeouts, 2) delays between the time a message is received and the time it's acted upon.
Usually, this identifies problems that I can fix in the code I can control. This improves things, but then I do it all over again, because chances are pretty good that I missed something the last time.
The result was that a system of asynchronous message-passing can be made to run quite fast, once preventable sources of delay have been eliminated.
There is a tendency in posting questions about performance to look for magic fixes to improve the situation. But, the real magic fix is to refine your diagnostic technique so it tells you what to fix, because it will be different from anyone else's.
An easy solution to this would be once the application get's fired, make a Long Polling connection with the server (you can choose when this connection need's to establish prior hand, and when to disconnect), but that is a kind of a hack if you want to avoid all the sniffing of packets with less api exposure iOS provides.
is streaming a viable option?
will there be a performance difference on the server end depending on which i choose?
is one better than the other for this case?
I am working on a GWT application with Tomcat running on the server end. To understand my needs, imagine updating the stock prices of several stocks concurrently.
Do you want the process to be client- or server-driven? In other words, do you want to push new data to the clients as soon as it's available, or would you rather that the clients request new data whenever they see fit, even though that might not be once/second? What is the likelyhood that the client will be able to stick around to wait for an answer? Even though you expect the events to occur once/second, how long does it take between a request from a client and the return from the server? If it's longer than a second, I'd expect you to lean towards pushing the events to the clients, though the other way around, I'd expect polling to be okay. If the response takes longer than the interval, then you're essentially streaming anyway, since there's a new event ready by the time the client receives the last one, so the client could essentially poll continually and always receive events - in this case, streaming the data would actually be more lightweight, since you're removing the connection/negotiation overhead from the process.
I would suspect that server load to be higher for a client-based (pull) subscription, instead of a streaming configuration, since the client would have to re-negotiate the connection each time, instead of leaving a connection open, but each open connection in a streaming model would require server resources as well. It depends on what the trade-off is between how aggressive your negotiation process is vs. how much memory/processing is required for each open connection. I'm no expert, though, so there may be other factors.
UPDATE: This guy talks about the trade-offs between long-polling and streaming, and he seems to say that with HTTP/1.1, the connection re-negotiation process is trivial, so that's not as much of an issue.
It doesn't really matter. The connection re-negotiation overhead is so slim with HTTP1.1, you won't notice any significant performance differences one way or another.
The benefits of long-polling are compatibility and reliability - no issues with proxies, ports, detecting disconnects, etc.
The benefits of "true" streaming would potentially be reduced overhead, but as mentioned already, this benefit is much, much less than it's made out to be.
Personally, I find a well-designed comet server to be the best solution for large numbers of updates and/or server-push.
Certainly, if you're looking to push data, streaming would seem to provide better performance, if your server can handle the expected number of continuous connections. But there's another issue that you don't address: Are you internet or intranet? Streaming has been reported to have some problems across proxies, much as you'd expect. So for a general purpose solution, you would probably be better served by long poll - for an intranet, where you understand the network infrastructure, streaming is quite likely a simpler, better performance solution for you.
The StreamHub GWT Comet Adapter was designed exactly for this scenario of streaming stock quotes. Example here: GWT Streaming Stock Quotes. It updates the stock prices of several stocks concurrently. I think the implementation underneath is Comet which is essentially streaming over HTTP.
Edit: It uses a different technique for each browser. To quote the website:
There are several different underlying
techniques used to implement Comet
including Hidden iFrame,
XMLHttpRequest/Script Long Polling,
and embedded plugins such as Flash.
The introduction of HTML 5 WebSockets
in to future browsers will provide an
alternative mechanism for HTTP
Streaming. StreamHub uses a "best-fit"
approach utilizing the most performant
and reliable technique for each
browser.
Streaming will be faster because data only crosses the wire one way. With polling, the latency is at least twice.
Polling is more resilient to network outages since it doesn't rely on a connection being kept open.
I'd go for polling just for the robustness.
For live stock prices I would absolutely keep the connection open, and ensure user alert/reconnection on disconnect.