On 03/Sep/2009 12:29, Regis wrote: > Tim Ellison wrote: >> A minor comment first :-) Please check return values for : >> >> + vect = (struct iovec*) hymem_allocate_memory(sizeof(struct iovec) * >> length); >> + >> + message = (*env)->GetPrimitiveArrayCritical(env, addrs, >> &isCopyMessage); >> + cts = (*env)->GetPrimitiveArrayCritical(env, counts, &isCopyCts); > > Yes, will add it, thanks. > >> >> >> A further enhancement is to have two versions of primitives, one that >> deals with direct buffers and one that deals with java heap buffers, so >> that there is (potentially) no data copying required for the java-heap >> buffers version that you have got today: > > One case stop me to do that is a buffer array contains direct and java > heap buffers both. In this case, either copying java heap buffres to > direct buffers or passing the whole array to native directly.
Yes, good point. > If pass the array to native directly, it need to call isDirect and > AddressUtil.getDirectBufferAddress in native code, as I understand, call > java methods from native side is like reflection, even more expensive, > so I chose copying all java heap buffers to direct buffers, at least it > fast when most buffers are direct and size of java heap buffers are not > too big. No need to use call back into Java code to do this, there are already JNI functions you can use: jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz); void* GetDirectBufferAddress(JNIEnv* env, jobject buf); See the spec at http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html However, you cannot always get the backing array from a ByteBuffer, so you still have three cases to deal with: 1. the direct byte buffer (by address) 2. the heap byte buffer with backing array (may be pinned/copied) 3. the heap byte buffer without an array (must be copied) For case (3) likely it is best to copy into a direct byte buffer to ensure it does not get copied again, so you end up passing only types (1) and (2) into the native. > One possible solution I can think is adding a new native call > > writevDirect(JNIEnv *env, jobject thiz, jobject fd, jobject bufferArray, > jobject addrs, jobject counts, jint length) > > passing buffer array and native addresses of direct buffers together, if > element of addrs is 0, the corresponding buffer is not direct. Well, > this method is a little bit hard to understand, it has 7 parameters.... I agree. Maybe the best way is to pass them in as jobjects and let the native code sort out the direct / heap buffers -- using the address directly and getting access to the bytes respectively. >> + if (!buffer.isDirect()) { >> + src[i] = ByteBuffer.allocateDirect(buffer.remaining()); >> + int oldPosition = buffer.position(); >> + src[i].put(buffer); >> >> some VMs will pin the java heap memory accessed in JNI >> (GetByteArrayElements), so if you can get hold of the ByteBuffer#array() >> you can pass a set of pointers to the backing arrays and maybe send the >> data directly. >> >> Looking forward to seeing the readv impl too ;-) > > Sure, it's on my TODO list :) Cool. Regards, Tim
