You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RxSwift图片处理流程性能优化方案咨询

RxSwift图片重绘流程性能优化建议

核心优化:调整并发策略

原流程中concatMap强制串行执行所有任务,而flatMap默认并发数不足,这是多图片处理慢的核心原因。针对不同任务类型(IO密集/CPU密集)设置合理并发数,最大化利用设备资源:

func redrawChapter(pages: [Resource]) -> Single<[UIImage]> {
    return Observable
        .from(pages)
        // 图片下载是IO密集,可设置较高并发数(如4-8,依设备性能调整)
        .flatMap(maxConcurrent: 6) { self.getImage(resource: $0) }
        // Vision文本识别可利用GPU,适当设置并发数
        .flatMap(maxConcurrent: 4) { self.recognizeText(image: $0) }
        // 翻译是网络IO,控制并发避免接口限流
        .flatMap(maxConcurrent: 2) { self.translate(image: $0.0, synopsys: $0.1) }
        // 图片重绘是CPU密集,按设备核心数设置并发(如2-4)
        .flatMap(maxConcurrent: 3) { self.redrawImage(image: $0.0, synopsys: $0.1) }
        .toArray()
}

简化Observable创建,消除冗余转换

多处存在不必要的Observable转Single操作,增加调度开销,直接用Single相关操作符简化:

优化图片下载函数

利用Kingfisher官方Rx扩展(需导入KingfisherRx),避免手动创建Single:

private func getImage(resource: Resource) -> Single<UIImage> {
    KingfisherManager.shared.rx.retrieveImage(with: resource)
        .map { $0.image }
}

优化文本识别函数

去掉多余的Observable包装,直接用Single.zip组合结果:

private func recognizeText(image: UIImage) -> Single<(UIImage, [Synopsis])> {
    return Single.zip(
        Single.just(image),
        self.imageProcessor.getRecognizedText(image: image).asSingle()
    )
}

优化翻译函数

移除冗余的compactMap,限制单图片内的翻译请求并发数,并将Maybe改为Single(只要有Synopsis就会有结果):

private func translate(image: UIImage, synopsys: [Synopsis]) -> Single<(UIImage, [Synopsis])> {
    return Observable.from(synopsys)
        .flatMap(maxConcurrent: 3) { synopsis in
            self.translator.translate(text: synopsis.text)
                .map { (synopsis.rect, $0) }
        }
        .map { Synopsis(text: $0.1, rect: $0.0) }
        .toArray()
        .map { (image, $0) }
}

图片重绘阶段优化

1. 后台线程执行渲染

图片重绘是CPU密集操作,默认在主线程执行会阻塞UI,将渲染逻辑移到后台队列:

private func redrawImage(image: UIImage, synopsys: [Synopsis]) -> Single<UIImage> {
    return Single.create { single in
        let queue = DispatchQueue.global(qos: .userInitiated)
        queue.async {
            let format = UIGraphicsImageRendererFormat()
            format.scale = 1
            
            guard let cgImage = image.cgImage else {
                single(.failure(NSError(domain: "ImageError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效图片"])))
                return
            }
            
            let size = image.size
            let bounds = CGRect(origin: .zero, size: size)
            
            let final = UIGraphicsImageRenderer(bounds: bounds, format: format).image { context in
                image.draw(in: bounds)
                
                // 提前预计算所有颜色,避免循环内重复计算
                let synopsisStyles = synopsys.map { syn in
                    let bgColor = cgImage.averageColorOf(rect: syn.rect)
                    return (syn, bgColor, bgColor.textColor())
                }
                
                for (syn, bgColor, textColor) in synopsisStyles {
                    self.setupLabel(
                        text: syn.text,
                        backgroundColor: bgColor,
                        textColor: textColor,
                        bounds: syn.rect,
                        context: context.cgContext
                    )
                }
            }
            
            DispatchQueue.main.async {
                single(.success(final))
            }
        }
        return Disposables.create()
    }
}

2. 优化文本绘制细节

  • 提前计算每个Synopsis的文本属性(字体、段落样式),避免循环内重复创建NSAttributedString
  • 复用相同颜色对象,减少内存分配
  • 检查setupLabel函数,缓存文本尺寸等计算结果,避免重复计算

其他优化建议

  • 缓存复用:对已下载图片、已识别文本区域、已翻译文本做本地缓存,避免重复处理相同资源
  • Vision性能调优:使用VNImageRequestHandler时,可降低输入图片分辨率(如果不需要高精度识别),减少计算量
  • 批量网络请求:将多个翻译文本打包成一个接口请求,减少网络握手开销

内容的提问来源于stack exchange,提问作者Artem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:31:19