android -- MemoryFile 内存文件(IO性能优化)
2014-04-28 12:32
941 查看
前些天还自已写了一个内存文件用于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?
<span style="font-size:16px;"> @SmallTest
public void testFileDescriptor() throws Exception {
MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
MemoryFile ref = new MemoryFile(file.getFileDescriptor(), file.length(), "r");
byte[] buffer;
<span style="color:#000066;"> // write to original, read from reference
file.writeBytes(testString, 0, 2000, testString.length);
buffer = new byte[testString.length];
ref.readBytes(buffer, 2000, 0, testString.length);
compareBuffers(testString, buffer, testString.length);</span>
file.close();
ref.close(); // Doesn't actually do anything, since the file descriptor is not dup(2):ed
}
</span>
比较数据函数:
[java] view
plaincopyprint?
<span style="font-size:16px;"> private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception {
for (int i = 0; i < length; i++) {
if (buffer1[i] != buffer2[i]) {
throw new Exception("readBytes did not read back what writeBytes wrote");
}
}
}</span>
ok, 使用非常简单
下面来分析下其实现的主要原素,大内存数据读写肯定离不开内存映射,这里必须使用到了 mmap / munmap
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
jint length, jint prot)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
<span style="color:#009900;">jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);</span>
if (!result)
jniThrowException(env, "java/io/IOException", "mmap failed");
return result;
}
static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
{
<span style="color:#009900;"> int result = munmap((void *)addr, length);</span>
if (result < 0)
jniThrowException(env, "java/io/IOException", "munmap failed");
}</span>
分配内存使用匿名内存实现:
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
{
const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
int result = ashmem_create_region(namestr, length);
</span>
数据读和写实现:
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
...
<span style="color:#3333FF;">env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);</span>
return count;
}
static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
...
<span style="color:#3333FF;">env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);</span>
return count;
}
</span>
应用场合:
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?
<span style="font-size:16px;"> @SmallTest
public void testFileDescriptor() throws Exception {
MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
MemoryFile ref = new MemoryFile(file.getFileDescriptor(), file.length(), "r");
byte[] buffer;
<span style="color:#000066;"> // write to original, read from reference
file.writeBytes(testString, 0, 2000, testString.length);
buffer = new byte[testString.length];
ref.readBytes(buffer, 2000, 0, testString.length);
compareBuffers(testString, buffer, testString.length);</span>
file.close();
ref.close(); // Doesn't actually do anything, since the file descriptor is not dup(2):ed
}
</span>
比较数据函数:
[java] view
plaincopyprint?
<span style="font-size:16px;"> private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception {
for (int i = 0; i < length; i++) {
if (buffer1[i] != buffer2[i]) {
throw new Exception("readBytes did not read back what writeBytes wrote");
}
}
}</span>
ok, 使用非常简单
下面来分析下其实现的主要原素,大内存数据读写肯定离不开内存映射,这里必须使用到了 mmap / munmap
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
jint length, jint prot)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
<span style="color:#009900;">jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);</span>
if (!result)
jniThrowException(env, "java/io/IOException", "mmap failed");
return result;
}
static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
{
<span style="color:#009900;"> int result = munmap((void *)addr, length);</span>
if (result < 0)
jniThrowException(env, "java/io/IOException", "munmap failed");
}</span>
分配内存使用匿名内存实现:
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
{
const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
int result = ashmem_create_region(namestr, length);
</span>
数据读和写实现:
[cpp] view
plaincopyprint?
<span style="font-size:16px;">static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
...
<span style="color:#3333FF;">env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);</span>
return count;
}
static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
jint count, jboolean unpinned)
{
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
...
<span style="color:#3333FF;">env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);</span>
return count;
}
</span>
相关文章推荐
- android -- MemoryFile 内存文件(IO性能优化)
- Android性能优化之内存篇
- 老李分享:Android性能优化之内存泄漏 2
- 【Android性能优化】内存泄露和内存溢出(OOM)的引发原因及优化方案
- Android性能优化-单例所引起的内存泄露
- Android 性能优化 - 彻底解决内存抖动 起源
- 【Android性能优化】内存泄露和内存溢出(OOM)的引发原因及优化方案
- Android性能优化:手把手带你全面了解 内存泄露 & 解决方案
- Android性能优化之内存优化
- Android内存性能优化(内部资料总结)
- Android性能优化 -- Memory Monitor工具检测内存泄露
- Android 性能优化之使用MAT分析内存泄露问题
- Linux 文件系统IO性能优化
- Android性能优化之巧用软引用与弱引用优化内存使用
- Android性能优化之内存泄漏分析工具LeakCanary
- Android 性能优化之使用MAT分析内存泄露问题
- Android 性能优化之使用MAT分析内存泄露问题
- Android性能优化之内存篇
- Android内存性能优化(内部资料总结) eoe转载