首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >零拷贝接收和消息大小

零拷贝接收和消息大小
EN

Stack Overflow用户
提问于 2016-09-28 15:52:21
回答 2查看 2.4K关注 0票数 3

当使用零拷贝接收消息时,是否有一种方法来查询接收消息的大小?

有了这个,我(尝试)实现零拷贝:

代码语言:javascript
复制
zmq_recv(sock, buf, sizeof(buf), 0);

我也试过:

代码语言:javascript
复制
zmq_msg_t msg;
zmq_msg_init_data (&msg, buf, sizeof(buf), nullptr, NULL);
zmq_msg_recv(&msg, sock, 0);
size_t len = zmq_msg_size(&msg);

这将返回正确的大小,但不填充buf。我认为zmq_msg_init_data不适合与zmq_msg_recv一起使用,并且消息在接收上重新构建。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-09-29 15:18:29

引用零副本上的指南

没有办法在接收时执行零拷贝: ZeroMQ为您提供一个缓冲区,只要您愿意,它就可以存储,但是它不会直接将数据写入应用程序缓冲区。

零拷贝只用于发送,而不是接收。

Oh和zmq_recv返回接收到的字节数。

票数 6
EN

Stack Overflow用户

发布于 2018-04-24 08:08:13

如果使用JeroMQ (纯Java for ZeroMQ),则可以通过ZMQ.Socket.setMsgAllocator在接收端实现零拷贝。

一般来说,我们只关心大型对象的零副本,因此您可以设置一个自定义消息分配器,例如:

代码语言:javascript
复制
class MappedMemoryMsgAllocator implements MsgAllocator {

static final MsgAllocatorHeap heap = new MsgAllocatorHeap();
private final int threshold;

public MappedMemoryMsgAllocator(int threshold) {
    this.threshold = threshold;
}

public MappedMemoryMsgAllocator() {
    this(1024 * 1024 * 4);
}

@Override
public Msg allocate(int size) {
    if ((threshold > 0) && (size > threshold)) {
        try {
            return new Msg(UtilsJNI.nativeMapMemory(size, UtilsJNI.PROT_WRITE, UtilsJNI.MAP_PRIVATE));
        } catch (IOException e) {
            Log.d(TAG, "allocate:: fail to mmap", e);
            return null;
        }
    } else {
        return heap.allocate(size);
    }
}

public static void forceFreeMsgArray(zmq.Msg[] msgs) {
    if (msgs != null) {
        for (zmq.Msg msg : msgs) {
            final ByteBuffer buf = msg.buf();
            if (buf.isDirect()) {
                try {
                    UtilsJNI.nativeUnmapMemory(buf);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

本机C++代码:

代码语言:javascript
复制
extern "C"
JNIEXPORT jobject
UtilsJNI_nativeMapMemory(JNIEnv *env, jobject clazz, jlong size,
                                              jint protection, jint mapFlags) {
    void *pAddr = mmap64(NULL, size, protection, mapFlags|MAP_ANONYMOUS, -1, 0);
    if (pAddr == NULL) {
        env->ThrowNew(env->FindClass("java/io/IOException"), "fail to mmap");
        return NULL;
    } else {
        return env->NewDirectByteBuffer(pAddr, size);
    }
}

extern "C"
JNIEXPORT void
UtilsJNI_nativeUnmapMemory(JNIEnv *env, jobject clazz, jobject buffer) {
    if (munmap(env->GetDirectBufferAddress(buffer), env->GetDirectBufferCapacity(buffer)) < 0) {
        env->ThrowNew(env->FindClass("java/io/IOException"), "fail to munmap");
    }
} 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39752266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档