1 Results for 'TextBlock'

  1. 2007.07.17 [Silverlight] TextBlock의 성능 문제 (8)
동기식 비동기식 무엇이 다르단 말인가? 에서 트랙백.
관련 스레드로, 네이버 실버라이트 카페도 참고.
 
TextBlock의 성능 문제

아주 심플하게 제목이 결론이에요.

좀 더 구체적으로 얘기하자면 다량의 메모리와 렌더링을 요구하는 오브젝트를 실버라이트 페이지의 루트 캔버스에 추가(Children.Add)했을 때 이 오브젝트를 렌더링하기 위한 시간이 상당히 길고 이 시간 동안 실버라잇 런타임이 프리징 되는 문제. 라고 할 수 있겠네요.

먼저 이 상황을 시뮬레이션 하는 예제를 먼저 돌려 보세요.
http://gongdo.oranc.co.kr/Silverlight/Samples/TextBlockPerformanceIssue/TestPage.html


샘플 프로젝트는 아래에서 다운로드.
TextBlockPerformanceIssue.zip

TextBlock 성능 문제 샘플 프로젝트


아래는 시뮬레이션의 예제에요.



각 버튼들의 이벤트 핸들러에는 10, 100, 1000, 5000, 10000, 50000 라인의 텍스트를 동적으로 생성하여 TextBlock으로 추가하는 코드가 작성되어 있어요. 그리고 코드의 각 진행 단계마다 진행 시간을 밀리세컨드 단위까지 표시하고 있고요.

이때 1000라인 까지는 아무런 문제 없이 부드럽게 진행되다가 5000라인쯤 되면 뭔가 답답하게 올라오고 10000라인쯤 되면 눈에 띄는 성능저하가 일어나며 50000라인쯤 되면 단순히 빙글빙글 돌아가는 애니메이션이 느려질 정도로 급격한 성능저하가 일어나요.

어디에서 문제가 일어나는가?
로그를 잘 보면 문자열을 1000라인이든 50000라인이든 작성하는 것 자체는 시간이 전혀 안 걸려요. 그리고 TextBlock을 코드-비하인드에서 동적으로 생성하거나 긴 문자열을 Text 속성에 설정하거나 하는 행위까지도 시간이 거의 안 걸리죠. 그런데, 이 TextBlock을 루트 캔버스의 Children에 추가하는 순간 라인이 길 수록 부하가 대폭 증가하는 것을 볼 수 있어요. 정확하지는 않지만, 아마 선형으로 증가할 거라고 예상해요.

왜 느려지는가?
이 부분은 전적으로 제 추측일 뿐이에요. 아직 공식적인 답변이나 의견은 얻지 못했으니 감안하고 봐주세요.
그렇다면 TextBlock 개체를 실버라이트 페이지의 개체 트리에 추가하는 순간에 문제가 생길 거라고 성급하게 예측할 수 있지만, 사실 이 시간 역시 그리 오래 걸리지 않는다고 봐요. 개체가 추가되기 위해 시간이 걸리는 게 아니라 개체를 렌더링, 화면에 뿌리기 위한 오버헤드가 크다는 것을 알 수 있어요.

어떻게 알았냐? 바로 5만 라인쯤 추가하면 아무것도 안 해도 옆에서 돌고 있는 애니메이션까지 느려지기 때문이죠. 그 얘기는 애니메이션을 렌더링 할 때 TextBlock 역시 새로 렌더링 될 텐데, 이 때 이 TextBlock을 렌더링 하는 시간이 오래 걸리기 때문에 애니메이션 까지 느려지는 거죠.

그렇다면 왜 느려질까요?
다시 한번 강조하지만 어디까지나 제 추측이에요.

제 예상으로는 TextBlock의 컨텐츠(여기에서는 Text 속성)을 렌더링 할 때 조금 똑똑한 런타임이라면 한번은 모든 Text를 렌더링 하겠지만 Text가 바뀌거나 어떤 변형이 가해지지 않은 이상 렌더링 된 결과 스냅샷을 메모리에 저장해놨다가 다음 렌더링 요청때 해당 스냅샷을 사용하여 화면에 뿌리고 또한 화면에 표시되지 않는 영역에 대한 렌더링은 하지 않는 클리핑 동작을 할거에요.

그런데, 이렇게 까지 일정하게 느려진다는 것은 위의 두 가지 동작중 적어도 하나는 하고 있지 않다는 얘기가 돼요. 말하자면 렌더링 요청이 있을 때마다 모든 Text 내용을 렌더링 하느라 느려지거나 렌더링 하지 않아도 될 영역까지 렌더링 하느라 느려지거나 최악의 경우 이 두 가지 짓을 다 할 수 있다는 거죠.

남은 건 절망 뿐인가~ 예~예에~♬
물론 그렇진 않죠.
이것은 비공식 채널에서 얼핏 스쳐 본 내용이라 잘못 본 걸 수도 있지만, 실버라잇 베타, 알파의 많은 엘리먼트나 코드들이 디버그 코드라고 해요. 그래서 릴리즈되면 자연히 해결된 문제도 많다는 거죠.

그리고 실버라잇에서 String의 할당 성능 문제 등의 자잘한 성능 이슈는 이미 Silverlight.net의 포럼에서 많이 지적되고 있는 문제에요. 이걸 그냥 넘어가진 않을거라고 생각해요.

그리고 더 중요한 것.
애초에 만 라인, 오만 라인씩이나 뿌리는 페이지를 기획 한 것부터가 문제라는 거에요!

아니 애시 당초 사람이 웹 페이지에서 이런 대용량의 데이터를 한눈에 볼 수 있을 리가 없잖아요?
요즘처럼 AJAX다 뭐다 페이지의 리프레쉬 없이도 데이터를 연속적으로 표시할 수 있는 수단이 얼마든지 있는데 무조건 꾸겨 넣으려는 그 생각이 문제라고요!

이건 성능테스트를 하다가 흔히 빠질 수 있는 함정인데요, 저도 처음에 이 문제 테스트를 위해 10, 100, 1000라인으로 테스트했어요. 그러다가 그 정도로는 별 부하가 안 걸리길래 막 늘렸죠 5000, 10000, 50000... 그러다가 만 라인쯤 되어서 부하가 막 걸리니까 '어? 이거 왜 그래? 뭐가 불만이야? 엉? 엉? 엉?' 이런 생각이 들었어요.

그렇지만, 현실적으로 이 정도 데이터를 표시하는 거라면 애초에 다른 수단을 쓰던가 아니면 비동기적인 페이징 기법을 사용했어야 한다는 게 정답이죠.

성능 테스트의 의욕은 높이 살 만 하지만, 눈앞의 성능 테스트에만 집착하다가 내가 왜 이 테스트를 하게 되었는지를 잊어버리면 안 된다는 거에요.

오우~ 실버라잇 만세?
물론 그렇진 않죠.
아까 얘기한 것처럼 분명히 렌더링 과정에서의 문제점은 있을 걸로 예상해요. 이것이 디버그 코드이기 때문에 그런지는 아직 모르겠지만 여하튼 위 예제에서의 TextBlock과 같이 커다란 메모리를 가지는 개체를 렌더링 할 때에도 같은 현상이 일어나요.

때문에 이런 성능 상의 문제는 차기 버전에서 반드시 개선되어야 할 사항이라고 생각해요.


결론
저야 일개 개발자로 무슨 힘이 있겠습니까. 그저 잘 되길 바랄 뿐이죠. 그런 점은 좀 아쉽네요.
한국 MS에도 개발 전도사를 뽑는다고 하는데 인선이 되면 무시무시하게 달려들 수도 있겠죠.

아, 사건 의뢰의 구체적인 답을 정리하지 않았군요.

낙훈님이 얘기한 문제는 동기/비동기 방식이 차이가 없는 게 아니라 데이터를 수신 받은 이후의 처리 과정이 동일했고 그 과정이 오래 걸리기 때문에 결과가 같아 보였을 뿐이라는 거에요.

그리고 그 원인은 위에서 설명한 대량의 렌더링이 필요한 개체를 루트 캔버스에 올렸을 때 발생하는 성능 저하에 있고요.
-끝-
신고
Posted by gongdo


티스토리 툴바