Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose performance optimization #137

Merged
merged 6 commits into from
Oct 16, 2023

Conversation

easyhooon
Copy link
Collaborator

람다함수를 함수 참조 형태로 변경
derivedStateOf 를 remember 로 wrapping
홈화면 내에 드롭다운 메뉴 위치 변경

@easyhooon easyhooon self-assigned this Oct 14, 2023
@easyhooon easyhooon added the refactoring Code restructure for better readability and efficiency label Oct 14, 2023
@easyhooon
Copy link
Collaborator Author

easyhooon commented Oct 14, 2023

Dropdown 메뉴의 위치 (DPoffset)는 히스토리를 확인해본 결과 실수로 다른 거 건드리다가 변경된 적이 없음..(처음부터 x = (-50).dp 였음)
왜 위치가 변했는지는 Compose 혹은 Material3 버전 변경 사항을 확인해봐야할듯

@easyhooon easyhooon merged commit a3d8be1 into develop Oct 16, 2023
1 check passed
@easyhooon easyhooon deleted the feaure/compose-performance-optimization branch October 16, 2023 01:53
Copy link
Collaborator

@likppi10 likppi10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

답이 늦었습니다..!

@@ -58,7 +57,9 @@ internal fun HomeRoute(
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val context = LocalContext.current
val bandalartCount by derivedStateOf { uiState.bandalartList.size }
val bandalartCount by remember {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

derivedStateO�f를 remeber로 감싸고 나서 derivedStateO�f를 recomposition으로부터 보존(?)한건가?
혹시 실제로 돌릴 때 이전과의 어떤 차이가 있었어?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://medium.com/androiddevelopers/jetpack-compose-when-should-i-use-derivedstateof-63ce7954c11b

https://velog.io/@beokbeok/%EC%96%B8%EC%A0%9C-derivedStateOf%EB%A5%BC-%EC%8D%A8%EC%95%BC%ED%95%A0%EA%B9%8C

자세한건 위의 글들 참고

나도 완벽히 이해한건 아니지만 말한것처럼 derivedStateOf를 remember 로 감싸주지 않으면 recomposition할때마다 재할당되서 derivedStateOf를 사용할때는 remember 를 특별한 경우가 아니면(특별한 경우가 언젠진 모르겠음) 세트로 같이 해줘야하더라고
실제로 지금 코드에서 remember {} 를 빼면 컴파일 단계에서 에러라고 remember 로 감싸라고 알려주더라

Copy link
Collaborator Author

@easyhooon easyhooon Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 실제로 돌릴 때 이전과의 어떤 차이가 있었어?

사실 이 모든게 탑바에 반다라드가 깜빡거리는걸 해결하기 위한 짓거리였는데 여전히 깜빡거리더라 난 list의 size를 탑바에 전달해주므로 이것을 컴포저블 내부에서 매번 연산을 해주는게 그 원인인가 싶어 연산이 최소한으로 이뤄지도록 해본건데 유의미한 변화는 없었음(recomposition 횟수의 감소 같은 것은 remember {} 를 없애고, 붙히고 build 했을때 report 의 변화를 확인하면 알 수 있을듯(이게 리포트를 심어둔 이유)
람다함수를 함수참조형태로 바꾼것도 매 recomposition 마다의 오버헤드를 줄이기 위해서 였고

근데 다시 생각해보면 '반다라트' 이미지만 깜빡거리고 탑바 오른쪽에 추가/목록<- 이 Text?는 깜빡이지 않는거보면 다른 이유같음
탑바의 recomposition이 문제라면 추가/목록 <- 이 텍스트도 같이 깜빡거려야 하는게 맞아가지고 ㅇㅇ..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

흠,, 이 문제가 가장 골치인 건 언제 깜빡거리느냐가 명확하지 않은게 한 몫하는 듯..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자력으로 해결 할 수 있을 줄 알았는디 잘 정리해서 질문을 한번 올려 봐야 할 듯

@@ -1,4 +1,4 @@
package com.nexters.bandalart.android.feature.home.ui
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내가 패키징만 옮기고, 각 파일 패키지 경로는 안 바꿔줬었구나,, ㅇㅂㅇ 감사링..

@@ -1,25 +1,25 @@
{
"skippableComposables": 31,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이쪽 파일은 어느샌가 문제가 생겨버렸네

@@ -1,24 +1,6 @@
package,name,composable,skippable,restartable,readonly,inline,isLambda,hasDefaults,defaultsGroup,groups,calls,
com.nexters.bandalart.android.core.ui.component.BandalartButton,BandalartButton,1,1,1,0,0,0,0,0,1,1,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뭐지 이 파일들이 의미하는게 뭘까..?

Copy link
Collaborator Author

@easyhooon easyhooon Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://sungbin.land/jetpack-compose-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-%EB%94%94%EB%B2%84%EA%B9%85-cf21ce431387

https://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8

자세한건 위의 링크들 참고

컴포즈의 성능 최적화 하기위한 방법중에 하나로 무분별한 Recomposition들을 줄여야 하는데 Recomposition을 skip하려면 각 컴포저블들의 정보들을 알아야하고(Stable한지 UnStable한지, Stable하면 Recomposition을 Skip할 수 있음) 이것들을 파악하기 위해서 매번 layout inspector 로 recomposition의 count 변화를 확인하면서 체킹하긴 어려우니까 빌드할때마다 이처럼 모듈별로 알아서 그 정보들을 다양한 형태로 제공 해주도록 해줬어

나는 어떤 파라미터가 UnStable해서 recomposition을 skip할 수 없는지를 찾는 용도로 도입했어
수많은 정보들이 있는데 나도 아직은 이 정보들을 전부 이해하진 모르겠음

@likppi10
Copy link
Collaborator

머야 이거 왜 사라져부렀어

@easyhooon
Copy link
Collaborator Author

easyhooon commented Nov 1, 2023

람다 함수( = { viewModel.func() } )를 함수 참조 형태( = viewModel::func )로 변경한 이유

람다 함수는 kotlin Compiler 에 의해 컴파일 될때 익명 클래스(anonymous class) 로 변환됨
함수를 호출할 때마다 새로운 익명 클래스의 객체, 람다 인스턴스를 생성하는 방식이라는 의미

람다 함수 안에서 사용 되는 뷰모델이 익명 클래스에 생성자 파라미터로 전달됨(문제되는 부분)
뷰모델은 Compose Compiler 에 의해 기본적으로 Stable 하다고 판단되지 않음

따라서 매 Recomposition 마다 해당 람다 함수는 새로운 인스턴스라고 판단됨
-> 매 Recomposition 마다 Compose Compiler 는 람다 함수가 변경되었다고 판단 -> 해당 스코프 전체가 Recomposition 됨


viewModel::func 과 같이 직접 함수를 참조하는 방식을 사용하면 이미 정의된 메소드나 함수에 대한 직접 참조를 만들게 되므로 새로운 익명 클래스를 생성할 필요가 없게 됨
Compose Compiler 는 해당 함수를 항상 동일한 인스턴스라고 판단하기 때문에 Recomposition 을 스킵할 수 있음(Recomposition이 필요한 부분만 Recomposition 이 수행됨)

항상 람다 함수를 함수 참조 형태로 변환할 수 있는 것은 아니지만, 가능한 경우 참조 형태로 변경할 것을 권장

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactoring Code restructure for better readability and efficiency
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants