- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个 Android 应用程序,它以大约 100Hz 的频率记录多个 Android 传感器。因此,如果我记录 10 个传感器,我每秒将大约 3000 个数据点写入一个文件(每个传感器通常有 3 个条目)。现在的问题是我想尽量减少这篇文章对应用程序其余部分的影响。具体来说,我不希望日志记录减慢事件传递速度......我想确保我在事件发生后立即收到事件,而不是延迟(我知道总会有一些延迟,因为 Android 不是实时并且由于传感器事件框架的“拉”性质)。
接下来,我将概述我的方法,该方法似乎效果不佳。我想就如何改进提出建议。
我目前的程序是这样的……
对于每个传感器,我创建了一个单独的线程,其中包含要记录的事件的 BlockingQueue。在线程内部,我有一个 while 循环,它从队列中拉出并使用缓冲写入器写入文件。当传感器管理器传递一个新的 SensorEvent 时,该事件被放入适当的队列中(从而触发另一个线程上的文件 IO),以免延迟传递 SensorEvent 的主线程。
我想在事件发生时立即获取事件,因此不要在传感器框架中引入任何延迟很重要。例如,如果我直接在 onEvent 回调中执行文件 IO,那么我担心事件可能会开始在管道中堆积,并且它们在最终交付时会过时。上述方法减轻了这些担忧。
但是还有一个问题……
尽管文件 IO 发生在传感器事件传递线程之外,但有时应用程序仍然感觉迟钝。也就是说,有时我会看到事件快速连续发生(例如,5 个事件在 1 毫秒内传递)。这表明尽管 IO 没有在传感器传输线程上发生,但传输线程仍在延迟。有人向我建议了几个原因:
我创建了太多 IO 线程。也许如果我将所有的写入推送到一个线程,我会增加当新事件进入时传感器传递线程处于 Activity 状态的可能性。在当前设置中,可能是所有 Activity 线程都用于文件IO 当事件到来时,导致事件备份,直到其中一个写入事件完成。
目前,我使用的是平面文件输出,而不是数据库。使用数据库进行检索的好处对我来说是显而易见的。我不清楚的是,如果我只将数据附加到文件中,我是否还应该期望数据库更快……也就是说,我永远不需要从文件中读取数据或将数据插入随机位置,我只是从字面上追加到文件的末尾。在我看来,在那种情况下,数据库不能比标准文件 IO 更快。还是我错了?
其他人建议垃圾收集器可能干扰了我的线程,问题的可能来源是由于正在创建大量事件而导致的内存抖动。
我应该从哪个角度来处理这个问题?
编辑:
以下是我用来将字符串写入文件的类。其中之一是根据 SensorEvent 类型创建的。
package io.pcess.utils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* This type of File Writer internally creates a low-priority {@link Thread}
* which queues data to be written to a specified file. Note that the
* constructor starts the {@link Thread}. Furthermore, you can then append a
* {@link String} to the end of the specified file by calling
*
* <pre>
* fileWritingThread.append(stringToAppend);
* </pre>
*
* Finally, you should tidy up by calling
*
* <pre>
* fileWritingThread.close();
* </pre>
*
* which will force the writer to finish what it is doing and close. Note that
* some {@link String}s might be left in the queue when closing, and hence will
* never be written.
*/
public class NonblockingFileWriter {
/**
* ---------------------------------------------
*
* Private Fields
*
* ---------------------------------------------
*/
/** The {@link Thread} on which the file writing will occur. */
private Thread thread = null;
/** The writer which does the actual file writing. **/
private BufferedWriter writer = null;
/** A Lock for the {@link #writer} to ensure thread-safeness */
private final Object writerLock = new Object();
/** {@link BlockingQueue} of data to write **/
private final BlockingQueue<String> data = new LinkedBlockingQueue<String>();
/** Flag indicating whether the {@link Runnable} is running. **/
private volatile boolean running = false;
/**
* The {@link Runnable} which will do the actual file writing. This method
* will keep writing until there is no more data in the list to write. Then
* it will wait until more data is supplied, and continue.
*/
private class FileWritingRunnable implements Runnable {
@Override
public void run() {
try {
while (running) {
String string = data.take();
synchronized (writerLock) {
if (writer != null) {
writer.write(string);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close();
}
}
};
/**
* ---------------------------------------------
*
* Constructors
*
* ---------------------------------------------
*/
public NonblockingFileWriter(String filename) {
this(new File(filename));
}
public NonblockingFileWriter(File file) {
writer = createWriter(file);
if (writer != null) {
running = true;
}
thread = new Thread(new FileWritingRunnable());
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
/**
* ---------------------------------------------
*
* Public Methods
*
* ---------------------------------------------
*/
/** Append the specified string to the file. */
public void append(String string) {
try {
data.put(string);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* Close the {@link BufferedWriter} and force the {@link Thread} to stop.
*/
public void close() {
running = false;
try {
synchronized (writerLock) {
if (writer != null) {
writer.close();
writer = null;
}
}
/**
* This string will not be written, but ensures that this Runnable
* will run to the end
*/
data.put("Exit");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create a {@link BufferedWriter} for the specified file.
*
* @param file
* @return
*/
private BufferedWriter createWriter(File file) {
BufferedWriter writer = null;
if (!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return writer;
}
}
if (file.canWrite()) {
boolean append = true;
try {
synchronized (writerLock) {
writer = new BufferedWriter(new FileWriter(file, append));
}
} catch (IOException e) {
e.printStackTrace();
}
}
return writer;
}
}
最佳答案
在您附加分析器并查看实际情况之前,一切都是猜测。根据一般经验,我会说第 1 点和第 3 点绝对有效。第 2 点少了;如果数据库比附加到文件更快,我认为这可能取决于实现质量和/或将 C 与 native API 结合使用,您应该能够克服差异。
关于 GC 负载,请查看 Looper
( api ) 和 Handler
( api )。使用这些,您可以将基于 BlockingQueue
的方法替换为完全不产生 GC 负载的方法。我写了一个blog post详细探讨这一点。
此外,如果您正在使用任何/所有清洁代码实践,可能是时候明智地使用脏代码(字段访问、可变性)来减轻内存流失了。
关于 IO 线程:我肯定会缩小到单个线程,并尝试将行分批写入文件,而不是一个接一个。只要您避免显式调用 flush()
,缓冲的 Stream 或 Writer 可能会自行解决问题。
关于android - 记录大量 Android 传感器数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43641819/
我有一个网站。 必须登录才能看到里面的内容。 但是,我使用此代码登录。 doc = Jsoup.connect("http://46.137.207.181/Account/Login.aspx")
我正在尝试为我的域创建一个 SPF 记录并使我的邮件服务器能够对其进行评估。我在邮件服务器上使用 Postfix 并使用 policyd-spf (Python) 来评估记录。目前,我通过我的私有(p
我需要为负载平衡的 AWS 站点 mywebsite.com 添加 CName 记录。记录应该是: @ CNAME mywebsite.us-east-1.elb.amazon
我目前正在开发一个相当大的多层应用程序,该应用程序将部署在海外。虽然我希望它在解聚后不会折叠或爆炸,但我不能 100% 确定这一点。因此,如果我知道我可以请求日志文件,以准确找出问题所在以及原因,那就
我使用以下命令从我的网络摄像头录制音频和视频 gst-launch-0.10 v4l2src ! video/x-raw-yuv,width=640,height=480,framerate=30/1
我刚刚开始使用 ffmpeg 将视频分割成图像。我想知道是否可以将控制台输出信息保存到日志文件中。我试过“-v 10”参数,也试过“-loglevel”参数。我在另一个 SO 帖子上看到使用 ffmp
我想针对两个日期查询我的表并检索其中的记录。 我这样声明我的变量; DECLARE @StartDate datetime; DECLARE @EndDate datetime; 并像这样设置我的变量
在 javascript 中,我可以使用简单的 for 循环访问对象的每个属性,如下所示 var myObj = {x:1, y:2}; var i, sum=0; for(i in myObj) s
最近加入了一个需要处理大量代码的项目,我想开始记录和可视化调用图的一些流程,让我更好地理解一切是如何组合在一起的。这是我希望在我的理想工具中看到的: 每个节点都是一个函数/方法 如果一个函数可以调用另
如何使用反射在F#中创建记录类型?谢谢 最佳答案 您可以使用 FSharpValue.MakeRecord [MSDN]创建一个记录实例,但是我认为F#中没有任何定义记录类型的东西。但是,记录会编译为
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 3年前关闭。 Improve thi
我是 Sequelize 的新手并且遇到了一些语法问题。我制作了以下模型: // User sequelize.define('user', { name: { type: DataTyp
${student.name} Notify 这是我的output.jsp。请注意,我已经放置了一个链接“Notify”以将其转发到 display.jsp 上。但我不确定如何将 Stud
例如,这是我要做的查询: server:"xxx.xxx.com" AND request_url:"/xxx/xxx/xxx" AND http_X_Forwarded_Proto:(https O
我一直在开发大量 Java、PHP 和 Python。所有这些都提供了很棒的日志记录包(分别是 Log4J、Log 或logging)。这在调试应用程序时有很大帮助。特别是当应用程序 headless
在我的Grails应用程序中,我异步运行一些批处理过程,并希望该过程记录各种状态消息,以便管理员以后可以检查它们。 我考虑过将log4j JDBC附加程序用作最简单的解决方案,但是据我所知,它不使用D
我想将进入 MQ 队列的消息记录到数据库/文件或其他日志队列,并且我无法修改现有代码。是否有任何方法可以实现某种类似于 HTTP 嗅探器的消息记录实用程序?或者也许 MQ 有一些内置的功能来记录消息?
如果我有一条包含通用字段的记录,在更改通用字段时是否有任何方法可以模仿方便的 with 语法? 即如果我有 type User = // 'photo can be Bitmap or Url {
假设我有一个名为 Car 的自定义对象。其中的所有字段都是私有(private)的。 public class Car { private String mName; private
当记录具有特定字段时,我需要返回 true 的函数,反之亦然。示例: -record(robot, {name, type=industrial, ho
我是一名优秀的程序员,十分优秀!