【发布时间】:2016-02-12 21:52:40
【问题描述】:
我正在尝试在 Android 中创建一个与远程服务快速通信的程序(约 40,000 次/秒),但是所有 Android IPC 似乎都无法完成这项任务。我的第一次尝试涉及一个标准的 Messenger 系统,该系统无法超过每秒约 2,000 次,同样糟糕的是,它似乎被间歇性延迟打断。
MainActivity(使用 Messenger 测试)
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(使用 Messenger 测试)
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 完成的。尽管这也为 IPC 实现了 Binder,但我认为开销要少得多。然而,事实证明,AIDL 的效率并不比 Messenger 高得多,而且它也没有解决口吃的问题。
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);
}
}
}
在这两种情况下,我是否做错了什么会阻止我达到约 5,000/秒?还是有其他我不知道的 Android IPC 系统?
【问题讨论】:
-
在具有制造商提供的 ROM 的现成硬件上,您将无法以每秒约 40,000 次的速度持续执行任何操作而不会卡顿,更不用说跨进程了。安卓 SDK。 SDK 应用无法控制线程和进程调度。
-
你可以考虑原始的
Binder协议(transact/onTransact),它应该比 AIDL 快,但也不快,也可能是套接字或MemoryFile(我实际上从未使用过它,所以我'不确定它有多快)? -
@CommonsWare 我可以通过 telnet 通过本地网络获得大约 40,000 个远程服务,该远程服务本质上是 IPC,Android 上没有什么可以匹配的吗?
-
@Beryllium:
telnet不是 Android SDK 应用程序。telnet会遇到同样的基本问题,因为操作系统线程和进程调度程序不能保证给您足够的时间来完成您的处理目标。正如 pskink 建议的那样,您当然欢迎使用套接字,这将直接类似于使用telnet。也欢迎您确认Timer将让您达到约 40,000 个事件/秒,无论 IPC 是什么。我只是警告你,你最终可能会感到失望。 -
使用原始
Binders(和FLAG_ONEWAY)我能够在120-200毫秒内发送100.000个整数,当然不是使用100000个事务,而是每个事务连续打包100个整数,从而进行 1000 次交易,在鸸鹋上运行
标签: android performance android-service ipc android-binder