android -- MemoryFile 内存文件(IO性能优化)

来源:互联网 发布:mac 隐藏文件夹显示 编辑:程序博客网 时间:2024/04/30 13:27

前些天还自已写了一个内存文件用于http数据交互使用,没想到今天翻代码,尽然找到类似的现有实现,真是汗! 呵呵,那么就在这简要介绍一下吧!


应用场合:

1、对于I/O需要频繁操作的,主要是和外部存储相关的I/O操作,MemoryFile通过将 NAND或SD卡上的文件,分段映射到内存中进行修改处理,这样就用高速的RAM代替了ROM或SD卡,性能自然提高不少,对于Android手机而言同时还减少了电量消耗。

2、对于java与jni大数据交互的话使用起来还是相当方便,只要将数据格式定义好即可。


类  MemoryFile.java  

路径:frameworks\base\core\java\android\os


JNI 实现 frameworks\base\core\jni\android_os_MemoryFile.cpp


用法:MemoryFileTest.java 这个文件中有例子, 我这里列一下基本的用法函数

[java] view plaincopyprint?
  1. <span style="font-size:16px;">    @SmallTest  
  2.     public void testFileDescriptor() throws Exception {  
  3.         MemoryFile file = new MemoryFile("MemoryFileTest"1000000);  
  4.         MemoryFile ref = new MemoryFile(file.getFileDescriptor(), file.length(), "r");  
  5.         byte[] buffer;  
  6.   
  7. <span style="color:#000066;">        // write to original, read from reference  
  8.         file.writeBytes(testString, 02000, testString.length);  
  9.         buffer = new byte[testString.length];  
  10.         ref.readBytes(buffer, 20000, testString.length);  
  11.         compareBuffers(testString, buffer, testString.length);</span>  
  12.   
  13.         file.close();  
  14.         ref.close();  // Doesn't actually do anything, since the file descriptor is not dup(2):ed  
  15.     }  
  16. </span>  

比较数据函数:

[java] view plaincopyprint?
  1. <span style="font-size:16px;">    private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception {  
  2.         for (int i = 0; i < length; i++) {  
  3.             if (buffer1[i] != buffer2[i]) {  
  4.                 throw new Exception("readBytes did not read back what writeBytes wrote");  
  5.             }  
  6.         }  
  7.     }</span>  

ok, 使用非常简单


下面来分析下其实现的主要原素,大内存数据读写肯定离不开内存映射,这里必须使用到了 mmap / munmap 

[cpp] view plaincopyprint?
  1. <span style="font-size:16px;">static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,  
  2.         jint length, jint prot)  
  3. {  
  4.     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);  
  5.     <span style="color:#009900;">jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);</span>  
  6.     if (!result)  
  7.         jniThrowException(env, "java/io/IOException""mmap failed");  
  8.     return result;  
  9. }  
  10.   
  11. static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)  
  12. {  
  13.    <span style="color:#009900;"int result = munmap((void *)addr, length);</span>  
  14.     if (result < 0)  
  15.         jniThrowException(env, "java/io/IOException""munmap failed");  
  16. }</span>  

分配内存使用匿名内存实现:

[cpp] view plaincopyprint?
  1. <span style="font-size:16px;">static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)  
  2. {  
  3.     const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);  
  4.   
  5.     int result = ashmem_create_region(namestr, length);  
  6. </span>  

数据读和写实现:

[cpp] view plaincopyprint?
  1. <span style="font-size:16px;">static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,  
  2.         jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,  
  3.         jint count, jboolean unpinned)  
  4. {  
  5.      int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);  
  6.   
  7.      ...  
  8.      <span style="color:#3333FF;">env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);</span>  
  9.   
  10.      return count;  
  11. }  
  12.   
  13.   
  14. static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,  
  15.         jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,  
  16.         jint count, jboolean unpinned)  
  17. {  
  18.   
  19.     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);  
  20.       ...  
  21.    <span style="color:#3333FF;">env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);</span>  
  22.    return count;  
  23. }  
  24.  </span>  
0 0
原创粉丝点击