k2-fsa / sherpa-ncnn

Real-time speech recognition using next-gen Kaldi with ncnn without Internet connection. Support iOS, Android, Raspberry Pi, VisionFive2, LicheePi4A etc.
https://k2-fsa.github.io/sherpa/ncnn/index.html
Apache License 2.0
902 stars 138 forks source link

Android集成SherpaNcnn的性能问题 #271

Closed developerzjy closed 4 months ago

developerzjy commented 9 months ago

在demo代码中,加载100多M的模型后内存占用增加了200多M,demo中只有初始化模型和给sherpa喂音频数据识别的代码,没有相关的资源释放代码。

问题1. jni.cc文件中的底层方法没有注释,想问一下delete方法是用来做释放资源的吗? 问题2. 如果在不需要识别的时候释放sherpa,官方有最佳实践的做法吗。(考虑释放后,可能再次进入识别场景重新初始化启用识别)

csukuangfj commented 9 months ago

@developerzjy

https://github.com/k2-fsa/sherpa-ncnn/blob/eab10d65b55df3ba6d6fbcd402b13b72a977b143/android/SherpaNcnn/app/src/main/java/com/k2fsa/sherpa/ncnn/MainActivity.kt#L27

你释放这个 model, 就可以释放资源。

或者,你参考 https://github.com/k2-fsa/sherpa-ncnn/blob/eab10d65b55df3ba6d6fbcd402b13b72a977b143/android/SherpaNcnn/app/src/main/java/com/k2fsa/sherpa/ncnn/SherpaNcnn.kt#L54-L56 自己再加两个方法

    fun delete() {
        if (ptr != null) {
            delete(ptr)
            ptr = null
        }
    }

   fun new() {
        if (ptr != null) {
            return
        }
        if (assetManager != null) {
            ptr = newFromAsset(assetManager, config)
        } else {
            ptr = newFromFile(config)
        }
    }
developerzjy commented 9 months ago

@csukuangfj 感谢回复,delete()和new()方法可以使用

csukuangfj commented 9 months ago

@csukuangfj 感谢回复,delete()和new()方法可以使用

每次创建,都需要一定的时间,即 overhead.

developerzjy commented 9 months ago

@csukuangfj 感谢回复,delete()和new()方法可以使用

每次创建,都需要一定的时间,即 overhead.

对于java层来说,这个时间就是newFromAsset(assetManager, config)或newFromFile(config)方法的执行时间吗,这两个方法是会阻塞线程的同步方法吗?

demo中我加了synchronized锁,能够保证delete和new的顺序执行,只是不确定new方法内部是同步创建还是异步创建。 加synchronized后,测试多次顺序调用delete和new后,暂时没发现什么问题

csukuangfj commented 9 months ago

是 个 blocking call. 创建完才返回。

developerzjy commented 9 months ago

是 个 blocking call. 创建完才返回。

也就是说保证new方法执行完后再调用delete方法是没有问题的,感谢解答

csukuangfj commented 9 months ago

是 个 blocking call. 创建完才返回。

也就是说保证new方法执行完后再调用delete方法是没有问题的,感谢解答

如果是在同一个线程里调用 new -> delete -> new -> delete -> new -> delete, 那么你说得对

developerzjy commented 9 months ago

是 个 blocking call. 创建完才返回。

也就是说保证new方法执行完后再调用delete方法是没有问题的,感谢解答

如果是在同一个线程里调用 new -> delete -> new -> delete -> new -> delete, 那么你说得对

好的,我代码上做一下这个线程处理

csukuangfj commented 9 months ago

https://github.com/k2-fsa/sherpa-ncnn/blob/eab10d65b55df3ba6d6fbcd402b13b72a977b143/android/SherpaNcnn/app/src/main/java/com/k2fsa/sherpa/ncnn/MainActivity.kt#L27

这个不是多线程安全的。请只在一个线程里操作它