使用 Messengers 或 AIDL 的快速 IPC

Rapid IPC with Messengers or AIDL

我正在尝试在 Android 中创建一个程序,它可以与远程服务快速通信(~40,000/秒),但是所有 Android IPC 似乎都无法完成这个任务。我的第一次尝试涉及一个标准的 Messenger 系统,它不能做超过 ~2,000/秒的事情,同样糟糕的是它似乎间歇性延迟。

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 完成的。虽然这也实现了 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);
        }
    }
}

在这两种情况下,我是否做错了什么会阻止我超过 ~5,000/秒?还是有另一个我不知道的 Android IPC 系统?

做这样的事情:

MainActivity

// use it for writing: stream.write(byte[]) 
// (make sure to write as biggest data chunks as possible)
// or wrap it around some other streams like DataOutputStream
private OutputStream stream;

// ServiceConnection implementation
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
    try {
        ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
        stream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);

        Parcel data = Parcel.obtain();
        FileDescriptor readFileDescriptor = pipe[0].getFileDescriptor();
        data.writeFileDescriptor(readFileDescriptor);
        service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
    } catch (Exception e) {
        e.printStackTrace();
    }
    Log.d(TAG, "onServiceConnected " + stream);
}

远程服务

@Override
public IBinder onBind(Intent intent) {
    Log.d(TAG, "onBind ");
    return binder;
}

IBinder binder = new Binder() {
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ParcelFileDescriptor pfd = data.readFileDescriptor();
        final InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
        // do something with a 'stream', start a new Thread for example and read data in a loop
        ...
        ...
        return true;
    }
};