MPC NI 프로파일링 - Team-HGD/SniffMEET GitHub Wiki
작성자: 허혜민, 윤지성
MPC + NI 프로파일링을 통한 문제점 발견
MPC + NI 기능 테스트 기기 정보
- iPhone 15 pro & iPhone 12 mini
- iPhone 12 & iPhone 12 mini
프로필 드랍 중에 버튼을 누르는 경우 (Browsing을 동일 인스턴스로 다시 시도하는 경우)
1. App Crash
문제 상황
프로필 드랍을 시도한 후 다시 시도할 때
문제 원인
MultipeerConnectivity 프레임워크에서 Browsing을 시도한 browser에 대해서 연결이 끊어진 직후 다시 연결을 시도하했을 때 발생하는 에러 리포팅을 발견했다.
이미 browsing을 시도한 후 disconnect된 browser에 대해서 다시 browsing을 했을 때 발생하는 에러로 보여진다.
해결 과정
-
reset 함수 설정
전에 MPC 연결이 시도된적이 있을 때 reset 함수를 통해 MPC, NI 초기화 과정을 실행한 후 프로필 드랍 시도하도록 변경
// TryProfileDropUseCase
func reset() {
isNIConnected.value = false
profilePublisher.value = nil
transmissionFlag = []
isTransistioned = false
mpcManager = nil
niManager = nil
mpcManager = MPCManager()
niManager = NIManager(mpcManager: mpcManager!)
niManager?.niSession?.delegate = self
mpcManager?.session.delegate = self
}
Ref.
https://github.com/insidegui/MultipeerKit/issues/12
2. Memory Laek 문제
MPC + NI 과정에서 Leak를 실행했는데 27개 발생
- Memeory Leak를 살펴보니 MCPeerID, MCBrowser, MCAdvertiser 가 포함되어 있다.
3. 한쪽 핸드폰에서 일정 시간 딜레이 후 화면전환이 일어나는 현상
한쪽(A)에서는 NISession이 연결되자마자 화면전환이 일어나는데 다른 한쪽(B)에서는 핸드폰 위치를 계속 움직여야 화면전환이 일어나는 현상이 발생했다.
현재 프로필 드랍 동작 과정
(변경 후)
- MPC 연결 시도 → MPC 연결 → NI 연결 시도 → NI 연결 → 거리 및 방향 만족한다면 프로필 데이터 전송 → 데이터를 받았다면 수신 플래그 전달 → 프로필 데이터를 받고 상대방의 수신 플래그도 받았다면 연결 종료
(변경 전)
- MPC 연결 시도 → MPC 연결 →프로필 데이터 전송 → NI 연결 시도 → NI 연결 → 거리 및 방향 만족한다면. 프로필 데이터 전송 → 데이터를 받았다면 수신 플래그 전달 → 프로필 데이터를 받고 상대방의 수신 플래그도 받았다면 연결 종료
예상하는 문제 원인
- A에서 데이터를 계속 전송하고 있음에도 B에서 데이터를 수신하지 못하고 있음
→ 송신과 수신이 동시에 연속적으로 이루어지고 있어 수신이 잘 되지 않는 것으로 예상됨
적재된 Task가 너무 많아 Hang이 발생했고 이로 인해 수신된 데이터 처리가 늦어지는 것으로 추측했다.
- 디바이스 별로 NI 칩 위치에 따른 방향 조건 차이
문제를 해결하기 위해 시도한 것들
- 수신을 처리하는 Task Priority 높게 변경
기존에는 수신, 송신 Task priority가 모두 21로 동일했다. 이미 쌓인 Task가 모두 실행되고 수신한 데이터를 처리하는 것으로 보였다.
수신을 처리하는 Task의 priority를 높이면 화면전환이 데이터를 받자마자 이루어질 것으로 예상했다.
**func** session(_ session:, didReceive:, fromPeer:)
에서
수행되는 Task의 priority를 .high
로 변경했지만 여전히 동일 문제가 발생했다.
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
Task.detached(priority: .high) { [weak self] in
guard let self else { return }
SNMLogger.info("didReceive bytes \(data.count) bytes")
guard let mpcManager, let niManager else { return }
do {
let receivedData = try self.decoder.decode(MPCProfileDropDTO.self, from: data)
if let token = receivedData.token { // 토큰
let niConnected = niManager.handleReceivedDiscoveryToken(token)
isNIConnected.send(niConnected)
} else if let profile = receivedData.profile { // 프로필 데이터
Task { @MainActor [weak self] in
self?.profilePublisher.send(profile)
}
guard let receivedFlagData else { return }
// 수신 플래그 송신
mpcManager.send(data: receivedFlagData)
} else if let message = receivedData.transitionMessage { // 수신 여부 플래그
lock.lock()
transmissionFlag.insert(message)
lock.unlock()
}
if transmissionFlag.contains(Context.peerReceived) && isTransistioned {
niManager.endSession()
isTransistioned = false
}
} catch {
SNMLogger.error("Failed to decode received data: \(error)")
}
}
}
1초 동안 → NI 세션에 관련된 함수가 7번 호출됨
-
이미지 용량 변경
전송하려는 이미지의 용량을 변경해보았다. 24058563 bytes → 16038 bytes
줄이는 바로 프로필 드랍이 한쪽에서 딜레이되는 현상이 해결되었다. ㅎㅎ