为什么这段代码即使没有 synchronized 关键字也会有性能问题?
Why this code have performance issue even without synchronized keyword?
为什么下面的代码有性能问题,相机的帧不流畅。
public class VideoCaptureAndroid implements PreviewCallback, Callback{
private Integer deviceRotation = Integer.MAX_VALUE;
public VideoCaptureAndroid(Context context, int id, long native_capturer) {
deviceRotationNotifier = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) {
Log.d(TAG, "The device rotation angle is unknown.");
return;
}
synchronized(deviceRotation) {
if (deviceRotation != orientation) {
deviceRotation = orientation;
}
}
}
};
Exchanger<Handler> handlerExchanger = new Exchanger<Handler>();
cameraThread = new CameraThread(handlerExchanger);
cameraThread.start();
}
public synchronized void onPreviewFrame(byte[] data, Camera callbackCamera) {
int frameRotation = info.orientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frameRotation = (info.orientation - deviceRotation + 360) % 360;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
frameRotation = (info.orientation + deviceRotation) % 360;
}
onFrame(data, data.length, native_capturer, frameRotation);
camera.addCallbackBuffer(data);
}
}
看来如果我注释掉下面的代码,框架很流畅,没有性能问题。但是我没有在onPreviewFrame
中使用synchronized
访问deviceRotation
,为什么会受到onOrientationChanged
的影响?
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frameRotation = (info.orientation - deviceRotation + 360) % 360;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
frameRotation = (info.orientation + deviceRotation) % 360;
}
您指定的代码很可能不是问题所在。模运算速度很慢,但每帧只做一个模运算不会产生巨大影响。 frameRotation
值被传递给 onFrame()
,我们只能假设它正在应用矩阵或其他变换来旋转数据。这是一项昂贵的操作,很可能涉及使用一个或多个临时缓冲区(或 Bitmap
对象),它使用堆并且速度也很慢。我假设 info.orientation
被原封不动地传递给 onFrame()
将导致不调整框架。因此,删除您指定的 2 行将不会导致 onFrame()
中的繁重处理,这就是抖动消失的原因。
您可以使用 traceview 或 systrace 来更好地追踪以确认。
为什么下面的代码有性能问题,相机的帧不流畅。
public class VideoCaptureAndroid implements PreviewCallback, Callback{
private Integer deviceRotation = Integer.MAX_VALUE;
public VideoCaptureAndroid(Context context, int id, long native_capturer) {
deviceRotationNotifier = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) {
Log.d(TAG, "The device rotation angle is unknown.");
return;
}
synchronized(deviceRotation) {
if (deviceRotation != orientation) {
deviceRotation = orientation;
}
}
}
};
Exchanger<Handler> handlerExchanger = new Exchanger<Handler>();
cameraThread = new CameraThread(handlerExchanger);
cameraThread.start();
}
public synchronized void onPreviewFrame(byte[] data, Camera callbackCamera) {
int frameRotation = info.orientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frameRotation = (info.orientation - deviceRotation + 360) % 360;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
frameRotation = (info.orientation + deviceRotation) % 360;
}
onFrame(data, data.length, native_capturer, frameRotation);
camera.addCallbackBuffer(data);
}
}
看来如果我注释掉下面的代码,框架很流畅,没有性能问题。但是我没有在onPreviewFrame
中使用synchronized
访问deviceRotation
,为什么会受到onOrientationChanged
的影响?
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frameRotation = (info.orientation - deviceRotation + 360) % 360;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
frameRotation = (info.orientation + deviceRotation) % 360;
}
您指定的代码很可能不是问题所在。模运算速度很慢,但每帧只做一个模运算不会产生巨大影响。 frameRotation
值被传递给 onFrame()
,我们只能假设它正在应用矩阵或其他变换来旋转数据。这是一项昂贵的操作,很可能涉及使用一个或多个临时缓冲区(或 Bitmap
对象),它使用堆并且速度也很慢。我假设 info.orientation
被原封不动地传递给 onFrame()
将导致不调整框架。因此,删除您指定的 2 行将不会导致 onFrame()
中的繁重处理,这就是抖动消失的原因。
您可以使用 traceview 或 systrace 来更好地追踪以确认。