Android Socket High CPU usage - android

I did a client/server(android/pc) and it seems that network usage from client uses a lot of CPU. Like to receive only 4k-5k from network, the cpu rises to 33 milliseconds. The cpu can be higher than 90-100 milliseconds if data is higher like ~32k.
First, I've tried the client(network part) in java version and after in c and the problem is still there.
I profiled the server part that send data and it uses about 0 millisecond.
Some details:
TCP connection.
The client connects to the server, client sends request, server sends
data (chunk of 4-10k), client send request, server sends...
Network part is threaded.
Get data with (recv or recv/select).
Smart Phone: Nexus one.
Tested in profiler mode (only network part and display fps/milliseconds).
Tested in Wifi (computer, phone, network are close).
Let me know if you have any suggestions or questions.
Thanks.

Are you using BufferedOutputStream on Android side to write the data? If not, it writes it byte by byte, which would explain the high CPU usage.
If this is not the case, please add some source code to the question.

Related

Websocket giving various numbers depending on OS

I'm doing a little test where I send out a short string(4-8 bytes) to a client every 0.5 seconds from a Node.js server using ws. The client is either using iOS/Android or a web browser. The client does not send anything back to the server, except for TCP-ACKS I suppose. The weird thing is, when I'm debugging the app in iOS using XCode network report, I can only see that the client sends out some bytes(approx 500) when the connections establishes, probably during the HTTP handshake. The remaining time ZERO data is going out from the device, there is only data coming in. The same results is achieved when receiving data in Chrome and tracking the data using Nettop.
The thing that makes so confused is that on the Android, almost the same amount of data that goes in to the device goes out when inspecting the network usage with Android profiler/Battery Historian/TrafficStats. I have tried using different libraries for the Websocket implementation and using different Android devices.
I have a hard time believing the ACKS sent out by the android is as big as the message received, even though it's just a small string of four characters.
So my questions are:
Could the case be that Nettop/XCode network report is simply ignoring all the ACKS, so in reality as much data is sent out in Chrome/iOS as in Android?
Is there something 'Wrong' with the libraries used in Android or could it be something with its operating system?
Could an ACK be as big as a simple TCP-package with 4 characters in it?
The result below when using Websocket
The data received/transmitted when using Android Battery Historian
The data received/transmitted on iOS using Network Report
Could an ACK be as big as a simple TCP-package with 4 characters in it?
An ACK consists of the IP and the TCP header and no payload. With IPv4 this means at least 20 bytes IP header and 20 bytes TCP header, i.e. 40 bytes. A packet with 4 bytes payload is only larger by 4 bytes, i.e. 44 bytes or just 10%.
The network report in Android shows 68350 in vs. 61370 in bytes, which is a difference of 11%. This matches the expected difference.
I'm not familiar with what iOS measure here, but it probably either measures only the application payload (i.e. the 4 bytes) or simply ignores packets with no payload, i.e. the ACK's.

It takes too long to read data from the bluetooth chip

I'm working on a project which using bluetooth to send two bytes data to HC-05 module and receive from it. Everything is going well but there's one thing that I can't bear with, which is stated below.
I use System.currentTimeMills() to get the time interval between sending data and receiving ,and it takes no more than 1ms`` to detect whether there's data in the buffer ofinputStream. However, it takes about30~200msto readtwo bytesof data from thebluetooth` chip on my cell phone.
Dose anyone know how to reduce the time ? Or it's insolvable?
The primary bottleneck should be the protocol scheduling. I don't know how this particular module works, but in Bluetooth in general you have to wait for your timeslot to send or receive.
Suggestions:
Check if you can send more than 2 bytes at the time. The read time is stable, but you get more data transmitted each time.
Check if the API gives you scheduling options, so the wait time goes down.
For your use case I think things would be simpler with Bluetooth low energy (BLE). You will need another module, but IMO it is worth it.

Reading More then 20 byte from remote BLE device failed in Lollipop

We are facing one issue when reading characteristics from remote BLE device.
This issue happen in Android OS 5.0 and above.
Points are below to generate issue :
Make one peripheral device with one service and one characteristics.
Characteristics will have only read permission. Now set the value of this characteristics with more than 20 characters i.e. 20 bytes.
Now let peripheral device broadcast itself with one service and one characteristics.
Now launch any BLE scanner app from market and connect with this peripheral device.
Once successfully connected with peripheral device just try to read characteristics.
In this case it will not show any data and when debugging the app it show that it returns null data.
The above same case not working in the Android OS 5.0 and above.
Same case working in android 4.4.
So there is something change in Android OS 5.0 and above that internally disable readblob() request that can read data having more that 20 characters.
This can be simply achievable by splitting your data into 20 byte packets and implementing a short delay (i.e. using sleep()) between sending each packet.
You can use BluetoothGatt.requestMtu(). See the Official document of BluetoothGatt.requestMtu
Request an MTU size used for a given connection.
When performing a write request operation (write without response), the data
sent is truncated to the MTU size. This function may be used to request a larger MTU size to be able to send more data at once.
A onMtuChanged(BluetoothGatt, int, int) callback will indicate whether this operation was successful.
Requires BLUETOOTH permission.
If you want send more 20 bytes, you should define array byte[] include how many packet you want.
There is an example Android: Sending data >20 bytes by BLE
Also there is another example How to send more than 20 bytes data over ble in android?

How to start a method in the same time on 2 devices

I have 2 android phones phones, both connected to the same wifi, both with bluetooth.
I want some method that syncs somehow the phones and starts a function on the same time on both phones.
For example playing a song at the same time.
I already tried with bluetooth but its with lag, sometimes 0.5 secs. I want something in +- 0.01sec if possible.
Someone suggesting playing it in the future with 2-3 seconds, sending the time-stamp, but how do you sync the internal clocks of the devices then ?
Before calling that particular method, try to measure the latency between the two devices:
1.First device says Hi(store the current time)
2.Second device receives the Hi.
3.Second device says back Hi !!
4.First device receives the Hi.((storedTime - currentTime) / 2 )
Now you have the latency, send your request to second device to start your particular method and start it on first one after the latency.
Try to measure the latency 5 to 10 times to be more accurate.
you have a way to transfer data between the devices right ?
if so you can send a time-stamp which is in the future,
ex: if the present time stamp is 1421242326 you send 1421242329 or something and start the function at that time on both devices.
Basically use #Dula's suggestion (device 1 sends command to device 2 and gives a "start time" which lies in the future). Both devices then start the action at the same time (in the future).
To make sure that the devices are synchronized, you can use a server-based time sync (assuming that both devices have Internet access). To do this, each device contacts the same server (using NTP, or HTTP-based NTP, or contacts a known HTTP server, like www.google.com and uses the value in the "Date" header of the HTTP response). The "server-date" is compared to the system clock on the device, and the difference is the "time-offset from server-time". The time-offsets can be used to synchronize on the "server-time", which is then used as the time base for the actual action (playing the media, etc.).
If your WiFi router allows clients to talk to each other (many public hotspots disable this), you could implement a simple socket listener on one (or each) device and have the initiating device broadcast a message.
For more complicated things and network flexibility, I've had good success with connected sessions using AllJoin. There is a bit of a learning curve to do interesting things, but the simple stuff is pretty easy once you understand the architecture.
Use a server to provide a synchronous event to just the two clients who have decclared their mutual affinity (random as a parm and pair serializer Partner-1 or Partner-2 which they share prior to their respectve calls for the sync event).
Assume both clients on same subnet (packets from 2 events serialized on the server , arrive across the network at the 2 clients simultaneously client-side) This provides synchronous PLays by 2 , bound clients.
The event delivered by server is either a confirm to play queued selected track OR a broadcast( decoupled, more formal)
The only tricky thing is the server side algorythm implementing this:
Queue a pair of requests or error
Part1, part2 with same Random value constitute valid pair if both received before either times out.
On a valid pair schedule both to the same future event in their respective , committed responses.
OnSchedule do the actual IO for 2 paired requests. Respective packets will arrive back at respective clients at same time, each response having been subject to equal network latency
Ng if two diff carrier 4G or lte networks involved. (Oops)
This thing is possible via socket, you will send a event via socket then the other device receive that event. For learn socket io chat
maybe it's not the answer you are looking for but i think that due to the high precision you are wanting , you should look for a push technology, i advice you to take look at SignalR. It's real time technology which gives you abstraction of sending methods , it have a built-in methods like Clients.All.Broadcast that fit your needs.
You can try to use some MQTT framework to send message between two device, or into a set with more number of devices.

How can I increase the throughput of my BLE application?

I have an android client that functions as a central and have an app on my MAC (peripheral) that this central connects to and sends data.
At this point, I need to wait almost 100ms after I call writeCharacteristic(..) to receive the onCharacteristicWrite(..) callback. I am sending strings. If I send smaller strings, the throughput is great (understandably). When the string contains about 200 characters and I send 20 byte chunks, it takes almost a second before the entire string is seen at the peripheral. When I set the write type to NO_RESPONSE before writing the characteristic, I see no data on the peripheral.
After I connect, I have done the following to improve throughput:
Stopped discovery after services are discovered because it is an expensive operation
I set the write type to default first - When I do this, I see data on the peripheral. But, there is a significant delay. When I set the writeType to NO_RESPONSE, I see no data on the peripheral. I have no logic in onCharacteristicWrite(..) either. Sometimes, I see the data getting truncated on the peripheral.
I have set the desired connection latency to low on my mac app. Is there a way to set a value (as 7.5ms perhaps?).
When I set the write type to default and send a string of 200 characters - I split the string into 20 byte chunks. I now have 10 chunks to send. If I set characteristic value and call writeCharacteristic(..) in loop, I see no data. When I add a ~100ms delay after writeCharacteristic(..) before it executes the next iteration of the loop, I see data on the peripheral.
I see a huge increase in throughput between an iOS central - iOS peripheral. I don't see why Android central - iOS peripheral shouldn't work he same way. From my understanding, Android and iOS use the same chip.
Any reason the performance is so poor? Is there anything else I can do to improve throughput?
Please have a look at the MTU size. My experience:
Using a iOS central, the central automatically starts the MTU size negotiation with some large value. I think it is larger than 200 bytes.
On most Android devices I tested this does not start automatically but you have to start the MTU size negotiation by your app (central). If you do not do that, Android cuts your data into 20 byte pieces. This has big influence on your throughput.

Categories

Resources