Я пытаюсь создать программу на Android, которая быстро взаимодействует с удаленным сервисом (~ 40 000/сек), однако все Android IPC, похоже, не в состоянии выполнить эту задачу. Моя первая попытка включала стандартную систему Messenger, которая не смогла сделать больше ~ 2000/секунд, и в равной степени плохая была то, что она, казалось, прерывалась прерывистым отставанием.Rapid IPC с Messenger или AIDL
MainActivity (тест с Messengers)
public class MainActivity extends Activity implements ServiceConnection{
Messenger mServiceMessenger;
Messenger mClientMessenger = new Messenger(new ClientHandler());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServiceMessenger = new Messenger(service);
Message m = Message.obtain();
m.replyTo = mClientMessenger;
try {
mServiceMessenger.send(m);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
public class ClientHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Log.d("Spam","Message Received");
}
}
}
RemoteService (тест с Messengers)
public class TestService extends Service {
private Messenger mServiceMessenger = new Messenger(new ServiceHandler());
private Messenger mClientMessenger;
private Random r = new Random();
public TestService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return mServiceMessenger.getBinder();
}
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
@Override
public void run() {
Bundle b = new Bundle();
b.putInt("INT",r.nextInt());
b.putLong("LONG",r.nextLong());
b.putBoolean("BOOL",r.nextBoolean());
b.putFloat("FLOAT",r.nextFloat());
b.putDouble("DOUBLE",r.nextDouble());
b.putString("STRING",String.valueOf(r.nextInt()));
Message msg = Message.obtain();
msg.setData(b);
try {
mClientMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
public class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
mClientMessenger = msg.replyTo;
initBarrage();
}
}
}
Вторая попытка была сделана с AIDL. Хотя это также реализует Binders для IPC, я предположил, что он значительно меньше накладных расходов. Однако AIDL доказал, что он не будет значительно более эффективным, чем Messengers, и он также не решил проблему с заиканием.
MainActivity (тест с AIDL)
public class MainActivity extends Activity implements ServiceConnection{
IRemoteService mService;
TextView countTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,TestService.class);
bindService(intent,this, Context.BIND_AUTO_CREATE);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IRemoteService.Stub.asInterface(service);
try {
mService.registerCallback(mClientBinder);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
public final IServiceAidlCallback.Stub mClientBinder = new IServiceAidlCallback.Stub(){
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString){
Log.d("Spam","Callback Received");
}
};
}
RemoteService (тест с AIDL)
public class TestService extends Service {
private Random r = new Random();
private IServiceAidlCallback mClientCallback;
public TestService() {
super();
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
public void registerCallback(IBinder callback){
mClientCallback = IServiceAidlCallback.Stub.asInterface(callback);
initSpam();
}
};
public void initSpam(){
for(int i=0;i<10;i++) {
TimerTask task = new TimerTask() {
@Override
public void run() {
try {
mClientCallback.basicTypes(
r.nextInt(),
r.nextLong(),
r.nextBoolean(),
r.nextFloat(),
r.nextDouble(),
String.valueOf(r.nextInt()));
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,1,1);
}
}
}
я делаю что-то неправильно в любом из этих случаев, которые препятствовали бы мне получить выше ~ 5000/сек? или есть еще одна система для Android IPC, о которой я не знал?
Вы не собираетесь быть в состоянии сделать что-либо поддерживается на ~ 40000 раз в секунду без заикания, не говоря уже о разных процессах, на готовом оборудовании с поставляемым производителем ROM, f с Android SDK. Приложения SDK не контролируют планирование потоков и процессов. – CommonsWare
вы могли бы считать необработанным протоколом 'Binder' (' transact'/'onTransact'), который должен быть быстрее AIDL, но не так много, также сокеты или' MemoryFile', может быть (я никогда не использовал его на самом деле, поэтому я не уверен, насколько это быстро возможно)? – pskink
@CommonsWare Я могу получить ~ 40 000 через локальную сеть с telnet для моей удаленной службы, которая по своей сути является IPC, нет ничего на Android, которая может соответствовать этому? – Beryllium