juijs / jui-chart

SVG-based JUI chart that can be used in the browser and Node.js. Support many types of charts. (Dashboard, Map, Topology, Full 3D, Realtime)
https://codepen.io/collection/nLydod/
57 stars 25 forks source link

메모리 점유등의 문제로 정상구동되지 않는 문제 #118

Open static-voidmain opened 7 years ago

static-voidmain commented 7 years ago

많이 귀찮게 해드리는 것 같아 죄송하네요...^^;; 제가 현재 제공해주고 계시는 Chart library를 가지고 프로젝트를 하고 있습니다. 일종의 모니터링인데, 문제는 메모리 관리등의 문제 입니다.

차트가 CPU, Memory, Disk 등을 표현하는 차트가 있고, 다시 이 차트에 10개 컴퓨터에서 제공되는 CPU, Memory, Disk 사용량을 한 페이지에서 표시하고 있습니다. 그런데, 차트가 많아지거나 차트에 표현되는 Legend가 많아 질 수록 속도의 저하가 심각하게 나타나고 있는데, 이 것에 대한 좋은 대처방법이 없을까요? 참고할 만한 문서라도 확인 부탁드립니다....;;;

Chart 버전도 최근 버전이고, JQuery등도 최근 버전입니다.

easylogic commented 7 years ago

사용에 불편을 드려서 죄송합니다.

먼저 현상을 체크를 좀 해야겠는데요.

차트가 보통 몇개가 표시가 되나요?
혹시 이벤트가 걸려있는 차트가 많으신가요? legend 는 보통 몇개 까지 그려지나요?

저희가 나름 brush 하나에 대한 최적화를 하긴 했는데 많은 차트를 동시에 그리면서 하는 부분은 아직 부족한 부분이 있습니다.

관련해서 알려주시면 최대한 원인을 찾아보도록 하겠습니다.

static-voidmain commented 7 years ago

일단 차트는 8개 정도 되구요. legend는 컴퓨터가 몇대야에 따라서 달라지니다. 그래도 대략을 따지자 하면 대략 10개 정도가 될 듯 합니다(현재 테스트 환경에선 각 차트마다 6개의 레전드가 보여집니다).

brush를 말씀하시는데, 저도 테스트를 해보니 여러 Brush를 쓸경우 많이 느려져서 Brush를 하나만 쓰고 있습니다. 다만, legend가 많아 지니 또 느려지더군요....;;;;;

현재 저는 dateblock의 차트를 쓰고 있습니다. 혹시 더 알려드려야 하는 부분이 있을까요?

아! 그리고 크롬에서 Profile 로 디버깅을 해보니 _.each 함수가 메모리를 많이 점유하는듯 합니다. 일반 for문이나, jQuery의 $.each 함수를 쓰는 것에 비해 메모리를 많이 먹습니다. 확인 부탁드리겠습니다.

뭔가를 잘못 눌러서 "Close"되었었네요...;;;; Reopen해서 코멘트를 다시 달았습니다.

easylogic commented 7 years ago

혹시 한번에 그려지는 데이타 개수가 얼마정도 되는지 알 수 있을까요? dateblock 을 쓰고 계시면 보통 몇개까지 표시하시나요?

브러쉬는 어떤거 쓰시나요?

_.each 쓰는 부분은 따로 점검 해봐야겠습니다.

static-voidmain commented 7 years ago

잘 이해가 안가는 지만...데이터 갯수라는 것이 제가 생각하고 있는게 맞다면 1초당 3분을 해서 180개 입니다. 3분~5분정도를 표시하려고 합니다. 따라서 180~300개 정도가 될듯 합니다. brush는 line 입니다. 다음이 Chart 옵션으로 활용하고 있는 부분입니다.

{
      height : 130
      , padding : {left: 48, top : 10, bottom: 45 , right : 4}
      , theme: "monitoringdark"
      , axis : {
        x : {type : "dateblock", interval: 1, realtime : "minutes", format : "HH:mm"}
        , y : {  type : "range"
          , domain: function(d){
            var range = [0, 10];
            maxValue = 0;
            for(digit in d){
              if(maxValue < d[digit]){
                maxValue = d[digit];
              }
            }
            if(maxValue != 0) {
              range = [0, (maxValue * 10)];
            }
            return range;
          }
          , step : 4
          , line : true
          , format : formatKMBT}
        , data : [] /*이 부분이 대략 180개의 데이터 셋이 들어 갑니다.*/
      }
      , brush : {type : "line", target : []/*이 부분은 6~10개 정도의 Legend Target이 들어 갑니다*/, axis : 0, symbol : "curve", display:"max", format : function(d){return fn_GetDataSize(d);}}
      , widget :
        [{
          type : "cross",
          yFormat : function(d){
            return (d).toFixed(1);
          },
          xFormat : function(d) {
            return juiTime.format(d, "HH:mm:ss");
          }
        },
          { type : "legend" }
        ]
      , style : {
        titleFontSize : 12,
        titleFontWeight : 700,
        legendFontSize : 11
      }
      , render : true
    }
easylogic commented 7 years ago

보여주신 코드 상으로 문제될 게 없는 것 같은데 다시 한번 살펴봐야겠습니다.

예전에 메모리릭 관련된 부분이 있어서 수정을 했는데요. 혹시 jui chart 최신 버전을 사용하고 계신가요?

static-voidmain commented 7 years ago

네 그렇습니다....^^ 혹시 버전을 비교할 수 있을 만한 부분이 있나요?? 다운 받아 사용한지는 2개월도 안되었지만, 혹시 그 사이에 메모리 관련된 부분이 수정된거라면 비교해서 말씀 드리겠습니다.

참고로 말씀 드리자면 {data array(180) * legend(6~10) * chart(8)} 개수 만큼이 사용되고 있다고 보시면 됩니다.

easylogic commented 7 years ago

지금 적어 주신 옵션에서 render : false 로 두시고

실제 차트 렌더링 할 때 chart.render(false) 로 해서 한번 해보시기 바랍니다.

이렇게 하면 렌더링시 하는 부하를 조금 줄일 수 있게 됩니다.

static-voidmain commented 7 years ago

상당 부분 빨라지긴 했습니다. 그래도 여전히 버벅임이 존재합니다....^^ 그래도 상당히깔끔히 움직이긴 합니다...

seogi1004 commented 7 years ago

실시간 차트의 성능은 차트 자체의 성능보단 차트 렌더링하는 코드에 영향을 많이 받습니다. 렌더링 하는 부분에 대한 코드를 올려주시면 튜닝 포인트를 찾아보겠습니다.

static-voidmain commented 7 years ago

렌더링 하는 코드 라고 하시는 것이 어떤 의미신지? 저 위의 옵션을 선언하고 변수로 받아서 다음과 같이 실행하고 있습니다. 이게 렌더링 하는 코드를 말씀하시는 건지요?

with(chartVariable){ var arrayList = axis(0).data; with(arrayList){ shift(); arrayList.push({machineName : 39.02201}); } var start = new Date() - (1000 * 60 * 3), end = new Date(), domain = [start, end]; axis(0).updateGrid("x", {domain : domain}); delete domain; axis(0).update(arrayList); delete arrayList; render(); }

chrome의 profiles 기능으로 튜닝은 어느정도 했구요 Google 프로젝트 팀에서 말하는 Memory Leak 관련해서 튜닝포인트들에 대해서 추가적으로 튜닝완료 했습니다. _.each 는 chrome의 profile 기능을 통해서 메모리를 많이 먹는 것을 확인했고, 이를 일반적인 for 문 또는 $.each 등으로 변경했는데 메모리 적인 부분이 많이 개선 되었습니다. 그리고 마지막으로 render:false하니 더 많이 개선이 되었구요....;;;; 다만 아직도 버벅임이 있는데, 챠트를 사용하여 모니터링하는 대상의 Machine이 많아 지면 느려질 것 같아보입니다.

seogi1004 commented 7 years ago

정확히 말하면 데이터를 업데이트 하는 시점에 대한 코드를 말한 것이었습니다. ㅎㅎ (서버에서 데이터를 가져오는 부분에 대한 코드까지)

static-voidmain commented 7 years ago

제가 잘 이해가 안가서 드리는 질문이지만....시점 문제와 메모리 관련 질문이 어떤 연관성을 갖는 것인가요? 혹여 서버의 데이터 처리 문제와 클라이언트 브라우저에서 데이터를 콜하는 시점차를 두고 메모리 관련 부분에 대해 질문을 해주시는 건지요?

혹시 데이터를 가져오는 부분에 있어서 딜레이가 있는가 하는 질문이시라면 그런 딜레이가 생기지 않는 것이 서버 사이드에서 1초(정확히 1000밀리 세턴드)에 한번씩 websocket으로 푸싱을 하고 있고, 그 푸싱되는 시점에 데이터를 push(바로전에 공유해 드렸던 코드의 내용)하고 렌더링 하게 됩니다.

즉 서버사이드에서 데이터가 업데이트 되는 시기와, 클라이언트 레벨에선 setInterver(client에서 setInterval이나, setTimout 같은 함수는 쓰고 있지 않습니다)같은 javascript 메소드의 비동기 부분에서 메모리가 핸들링에 문제가 된다 보시는 거라면 그런 일은 없을 것이라 생각됩니다. 서버사이드에서 푸싱되는 시점에 데이터 업데이트 하고 렌더링 하는 거니까요.

이해를 제가 맞게 하고 답변을 드리는 것인지 모르겠지만, 혹시 제가 이해한 것이 부합하지 못하고, 개발자님께서 유스케이스가 있다면, 예로 말씀을 청하고자 합니다(서버사이드 코드 공개는 조심스러운 부분이 있는 터라;;;;;;). 로컬 개발중에는 수집기로 부터 데이터를 가져오거나 그 것을 client browser로 보내는 것에 (그리고 수집은 DB에서 가져오지 않습니다)I/O적인 딜레이나 이런 것이 존재하고 있진 않습니다. 500밀리세컨드(0.5)나 그 보다 작은 단위의 retrieve에서도 딜레이가 생기지 않습니다. UDP를 사용하고 있고, 이 것을 json으로 파싱하는데도 0.01 초 정도의 속도를 보이고 있습니다.