При сканировании текста в Android Vision происходит утечка памяти в Xamarin.Android
Заметив несколько сбоев на старых устройствах при использовании TextRecognizer
из библиотеки Android.Gms.Vision
Я решил профилировать его с помощью Android Studio, и результат был следующим:
Пока процесс запущен, даже если метод ReceiveDetections
пусто (никакой кодовой логики на моей стороне, кроме создания экземпляра компоновщика), использование памяти растет очень быстро, и приложение впоследствии падает в течение одной минуты. Из профилировщика я мог видеть, что память используется в byte[]
переменная в нативном коде.
Интересным фактом является то, что я также использую BarcodeDetector
из этой библиотеки, но это не вызывает утечки памяти. Наконец, я также профилировал свое приложение Xamarin.Android, используя профилировщик Xamarin, и код Mono занимает максимум пару МБ, поэтому мой код, похоже, не вызывает проблемы.
Я добавляю код, который я использую ниже:
public class Scanning : Activity, ISurfaceHolderCallback, IProcessor
{
private SurfaceView surfaceView;
private CameraSource cameraSource;
private const int RequestCameraPermissionID = 1001;
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
switch (requestCode)
{
case RequestCameraPermissionID:
if (grantResults[0] == Permission.Granted)
cameraSource.Start(surfaceView.Holder);
break;
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Scanning);
RequestedOrientation = ScreenOrientation.Portrait;
surfaceView = FindViewById<SurfaceView>(Resource.Id.surfaceView);
TextRecognizer textRecognizer = new TextRecognizer.Builder(ApplicationContext).Build();
if (textRecognizer.IsOperational)
{
cameraSource = new CameraSource.Builder(ApplicationContext, textRecognizer).Build();
surfaceView.Holder.AddCallback(this);
textRecognizer.SetProcessor(this);
}
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height) { }
public void SurfaceCreated(ISurfaceHolder holder)
{
if (CheckSelfPermission(Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
RequestPermissions(new string[]
{
Android.Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
cameraSource.Start(surfaceView.Holder);
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
cameraSource.Stop();
}
public void ReceiveDetections(Detections detections) { }
public void Release() { }
}
Я что-то пропустил на моей стороне, или это действительно ошибка библиотеки?
Если да, есть ли обходной путь?
1 ответ
Управляемые вызываемые обертки MCW (обертывание кода C# для Android API) могут содержать ссылку на некоторые объекты Java, содержащие другие данные (изображение отсканировано, текст...), так что GC не может освободить эту память.
У меня был похожий случай в одной кастомной привязке для распознавания изображений.
Решение состоит в том, чтобы понять, какие объекты могут содержать ссылки, и после того, как они больше не нужны для вызова вручную GC.Collect()
,
С этой точки зрения высокого уровня (взгляд) я бы назвал это в Release()
и / или после cameraSource.Stop();
Дай мне знать, если это работает. В противном случае мне понадобится образец репро, чтобы проверить его.