- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我是线程的新手(不要因为我下面的实现而杀了我:),我需要在一个单独的线程上对像素进行多次模糊处理(见下文)。它不是方框模糊的最有效实现(来自 Gaussian Filter without using ConvolveOp),但性能峰值不会出现在 Nexus 7 平板电脑上,但会出现在 Nexus 4 手机上。
我已经发布了我的测试示例(在 Android 4.2 上运行 - 见下文)。
我不认为这是由 GC 抖动内存引起的(它与峰值不一致)。
我认为这可能与缓存局部性或硬件内存抖动有关 - 但我不确定。
什么会导致尖峰?有时它们会突然发作 - 例如峰值 50%。有时它们起病缓慢 - 例如尖峰单调增加/减少,尖峰如下 -> 5%, 10%, 20%, 10%, 5%.
在进行繁重的数组处理时如何阻止它们发生?
这不会发生在我也测试过的 Nexus 7 平板电脑上(见下面的结果)
附带问题:正确休眠和重新启动我的线程的最佳方法是什么(线程新手)?
package com.example.test;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private MainThread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thread = new MainThread();
thread.setRunning(true);
thread.start();
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
thread.setRunning(true);
}
@Override
protected void onPause() {
super.onPause();
thread.setRunning(false);
}
}
package com.example.test;
import android.util.Log;
public class MainThread extends Thread {
int[] pixels;
int kernel_rows = 2;
int kernel_cols = 2;
int width = 512;
int height = 512;
@Override
public void run() {
while (running) {
long start = System.currentTimeMillis();
for (int row = kernel_rows / 2; row < height - kernel_rows / 2; row++) {
for (int col = kernel_cols / 2; col < width - kernel_cols / 2; col++) {
float pixel = 0;
// iterate over each pixel in the kernel
for (int row_offset = 0; row_offset < kernel_rows; row_offset++) {
for (int col_offset = 0; col_offset < kernel_cols; col_offset++) {
// subtract by half the kernel size to center the
// kernel
// on the pixel in question
final int row_index = row + row_offset
- kernel_rows / 2;
final int col_index = col + col_offset
- kernel_cols / 2;
pixel += pixels[row_index * width + col_index] * 1.0f / 4.0f;
}
}
pixels[row * width + col] = (int) pixel;
}
}
long stop = System.currentTimeMillis();
long delta = stop - start;
Log.d("DELTA", Long.toString(delta));
}
}
private boolean running;
public void setRunning(boolean running) {
this.pixels = new int[512 * 512];
this.running = running;
}
}
Nexus 4 手机(毫秒):
01-13 10:56:05.663: D/DELTA(13507): 76
01-13 10:56:05.773: D/DELTA(13507): 107
01-13 10:56:05.843: D/DELTA(13507): 77
01-13 10:56:05.923: D/DELTA(13507): 75
01-13 10:56:06.053: D/DELTA(13507): 127
01-13 10:56:06.133: D/DELTA(13507): 78
01-13 10:56:06.213: D/DELTA(13507): 81
01-13 10:56:06.293: D/DELTA(13507): 80
01-13 10:56:06.353: D/DELTA(13507): 77
01-13 10:56:06.433: D/DELTA(13507): 79
01-13 10:56:06.513: D/DELTA(13507): 79
01-13 10:56:06.624: D/DELTA(13507): 106
01-13 10:56:06.694: D/DELTA(13507): 76
Nexus 7 平板电脑(毫秒):
01-13 11:01:03.283: D/DELTA(3909): 84
01-13 11:01:03.373: D/DELTA(3909): 85
01-13 11:01:03.453: D/DELTA(3909): 85
01-13 11:01:03.543: D/DELTA(3909): 84
01-13 11:01:03.623: D/DELTA(3909): 85
01-13 11:01:03.703: D/DELTA(3909): 84
01-13 11:01:03.793: D/DELTA(3909): 85
01-13 11:01:03.873: D/DELTA(3909): 84
01-13 11:01:03.963: D/DELTA(3909): 85
01-13 11:01:04.043: D/DELTA(3909): 84
最佳答案
我想我可能已经在某种程度上减轻了 Nexus 4 上的这种影响。计算一致性仍然存在一些可变性,但它是可以忍受的 - 我认为 - 看不到太多巨大的尖峰 - 在线程启动/关闭之外。我已经使用 Android NDK 和 c p_threads 完成了此操作,以生成一个 native 线程,该线程主要由 Java(或者我被告知)单独保留,直到更改或关闭前台应用程序。
代码如下:
package com.example.test;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
static {
System.loadLibrary("native");
}
private native void init();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes and spawns native thread
init();
setContentView(R.layout.activity_main);
}
}
(应该放在Android项目根目录下的jni文件夹中)
#include <time.h>
#include <pthread.h>
#include <jni.h>
#include <android/log.h>
#define APPNAME "DELTA"
int* pixels;
int kernel_rows = 2;
int kernel_cols = 2;
int width = 60;
int height = 39;
int running = 1;
// from android samples
/* return current time in milliseconds */
static double now_ms(void) {
struct timespec res;
clock_gettime(CLOCK_REALTIME, &res);
return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
}
// initialize thread/begin it
jint Java_com_example_testa_MainActivity_init(JNIEnv* env, jobject javaThis) {
int i1 = 1;
pthread_t thread;
void *run();
pthread_create(&thread, NULL, run, &i1);
pthread_join(thread, NULL);
return 0;
}
// thread function
void *run(int *x) {
// init pixels within thread
pixels = (int*) malloc(sizeof(int) * width * height);
// loop until stopped - java won't interfere
// unless closed/switch application (or so I'm told)
while (running) {
double start = now_ms();
int row, col, row_offset, col_offset;
for (row = kernel_rows / 2; row < height - kernel_rows / 2; row++) {
for (col = kernel_cols / 2; col < width - kernel_cols / 2; col++) {
float pixel = 0;
// iterate over each pixel in the kernel
for (row_offset = 0; row_offset < kernel_rows; row_offset++) {
for (col_offset = 0; col_offset < kernel_cols;
col_offset++) {
// subtract by half the kernel size to center the
// kernel
// on the pixel in question
int row_index = row + row_offset - kernel_rows / 2;
int col_index = col + col_offset - kernel_cols / 2;
pixel += pixels[row_index * width + col_index] * 1.0f
/ 4.0f;
}
}
pixels[row * width + col] = (int) pixel;
}
}
double end = now_ms();
double delta = end - start;
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "%f", delta);
}
pthread_exit(0);
}
(应该放在Android项目根目录下的jni文件夹中)
LOCAL_PATH := $(call my-dir)
MY_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_PATH)
LOCAL_MODULE := native
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := native.c
include $(BUILD_SHARED_LIBRARY)
代码成本降低了约 20-30%,可变性降低了一个数量级。
代码是通过在根文件夹(可在此处找到:http://developer.android.com/tools/sdk/ndk/index.html)中从 Android 提供的 NDK 库执行 ndk-build
命令编译的。
Nexus 4(毫秒):
01-14 13:41:21.132: V/DELTA(23679): 56.554199
01-14 13:41:21.192: V/DELTA(23679): 58.568604
01-14 13:41:21.252: V/DELTA(23679): 59.484131
01-14 13:41:21.302: V/DELTA(23679): 56.768066
01-14 13:41:21.362: V/DELTA(23679): 54.692383
01-14 13:41:21.412: V/DELTA(23679): 51.823730
01-14 13:41:21.472: V/DELTA(23679): 55.668945
01-14 13:41:21.522: V/DELTA(23679): 56.920654
01-14 13:41:21.582: V/DELTA(23679): 56.371094
01-14 13:41:21.642: V/DELTA(23679): 58.507568
01-14 13:41:21.702: V/DELTA(23679): 59.697754
01-14 13:41:21.752: V/DELTA(23679): 53.990723
01-14 13:41:21.812: V/DELTA(23679): 55.669189
Nexus 7(毫秒):
01-14 13:41:25.685: V/DELTA(2916): 65.867920
01-14 13:41:25.745: V/DELTA(2916): 65.986816
01-14 13:41:25.815: V/DELTA(2916): 66.685059
01-14 13:41:25.885: V/DELTA(2916): 67.033936
01-14 13:41:25.945: V/DELTA(2916): 65.703857
01-14 13:41:26.015: V/DELTA(2916): 66.653076
01-14 13:41:26.085: V/DELTA(2916): 66.922119
01-14 13:41:26.145: V/DELTA(2916): 67.030029
01-14 13:41:26.215: V/DELTA(2916): 67.014893
01-14 13:41:26.285: V/DELTA(2916): 67.034912
01-14 13:41:26.345: V/DELTA(2916): 67.089844
01-14 13:41:26.415: V/DELTA(2916): 65.860107
01-14 13:41:26.485: V/DELTA(2916): 65.642090
01-14 13:41:26.545: V/DELTA(2916): 65.574951
01-14 13:41:26.615: V/DELTA(2916): 65.991943
关于android - 在 Nexus 4 上进行计算量大的数组处理时,会出现周期性的性能峰值是什么原因造成的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14299288/
我正在尝试创建一个包含 int[][] 项的数组 即 int version0Indexes[][4] = { {1,2,3,4}, {5,6,7,8} }; int version1Indexes[
我有一个整数数组: private int array[]; 如果我还有一个名为 add 的方法,那么以下有什么区别: public void add(int value) { array[va
当您尝试在 JavaScript 中将一个数组添加到另一个数组时,它会将其转换为一个字符串。通常,当以另一种语言执行此操作时,列表会合并。 JavaScript [1, 2] + [3, 4] = "
根据我正在阅读的教程,如果您想创建一个包含 5 列和 3 行的表格来表示这样的数据... 45 4 34 99 56 3 23 99 43 2 1 1 0 43 67 ...它说你可以使用下
我通常使用 python 编写脚本/程序,但最近开始使用 JavaScript 进行编程,并且在使用数组时遇到了一些问题。 在 python 中,当我创建一个数组并使用 for x in y 时,我得
我有一个这样的数组: temp = [ 'data1', ['data1_a','data1_b'], ['data2_a','data2_b','data2_c'] ]; // 我想使用 toStr
rent_property (table name) id fullName propertyName 1 A House Name1 2 B
这个问题在这里已经有了答案: 关闭13年前。 Possible Duplicate: In C arrays why is this true? a[5] == 5[a] array[index] 和
使用 Excel 2013。经过多年的寻找和适应,我的第一篇文章。 我正在尝试将当前 App 用户(即“John Smith”)与他的电子邮件地址“jsmith@work.com”进行匹配。 使用两个
当仅在一个边距上操作时,apply 似乎不会重新组装 3D 数组。考虑: arr 1),但对我来说仍然很奇怪,如果一个函数返回一个具有尺寸的对象,那么它们基本上会被忽略。 最佳答案 这是一个不太理
我有一个包含 GPS 坐标的 MySQL 数据库。这是我检索坐标的部分 PHP 代码; $sql = "SELECT lat, lon FROM gps_data"; $stmt=$db->query
我需要找到一种方法来执行这个操作,我有一个形状数组 [批量大小, 150, 1] 代表 batch_size 整数序列,每个序列有 150 个元素长,但在每个序列中都有很多添加的零,以使所有序列具有相
我必须通过 url 中的 json 获取文本。 层次结构如下: 对象>数组>对象>数组>对象。 我想用这段代码获取文本。但是我收到错误 :org.json.JSONException: No valu
enter code here- (void)viewDidLoad { NSMutableArray *imageViewArray= [[NSMutableArray alloc] init];
知道如何对二维字符串数组执行修剪操作,例如使用 Java 流 API 进行 3x3 并将其收集回相同维度的 3x3 数组? 重点是避免使用显式的 for 循环。 当前的解决方案只是简单地执行一个 fo
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有来自 ASP.NET Web 服务的以下 XML 输出: 1710 1711 1712 1713
如果我有一个对象todo作为您状态的一部分,并且该对象包含数组列表,则列表内部有对象,在这些对象内部还有另一个数组listItems。如何更新数组 listItems 中 id 为“poi098”的对
我想将最大长度为 8 的 bool 数组打包成一个字节,通过网络发送它,然后将其解压回 bool 数组。已经在这里尝试了一些解决方案,但没有用。我正在使用单声道。 我制作了 BitArray,然后尝试
我们的数据库中有这个字段指示一周中的每一天的真/假标志,如下所示:'1111110' 我需要将此值转换为 boolean 数组。 为此,我编写了以下代码: char[] freqs = weekday
我是一名优秀的程序员,十分优秀!