23

웹 작업자에서 실행될 때 스크립트의 성능을 향상 시키려고합니다. 그것은 크래시없이 브라우저에서 큰 텍스트 파일을 구문 분석하도록 설계되었습니다. 모든 것이 잘 작동하지만 웹 작업자를 사용할 때 대용량 파일의 성능에 심각한 차이가 있음을 알 수 있습니다.웹 작업자의 성능이 30 초 후에 급격히 떨어지는 이유는 무엇입니까?

그래서 나는 간단한 실험을 수행했습니다. 스크립트를 동일한 입력으로 두 번 실행했습니다. 첫 번째 실행은 페이지의 기본 스레드에서 스크립트를 실행했습니다 (웹 작업자 없음). 당연히이 때문에 페이지가 정지되어 응답하지 않게됩니다. 두 번째 실행을 위해 웹 작업자에서 스크립트를 실행했습니다. 이 실험 (< 100 ~ MB) 작은 파일의 경우

  • Test runner page
  • Script being executed

    • 는 성능 차이는 무시할 수있다. 그러나, 큰 파일에서 구문 분석 작업자 스레드에서 더 이상 약 20 배를 취합니다

      Performance of both scenarios on same graph

      파란색 라인이 예상된다. 그것은 단지 파일을 구문 분석하는 데 약 11 초가 걸릴해야하며, 성능은 상당히 안정 :

      Performance of script without web worker

      빨간색 선은 웹 노동자 내부의 성능이다. 그것은 훨씬 더 놀라운 일이다 :

      Performance of script in web worker

      처음 30 초 동안 지그재그 선 (재규어가 구문 분석 파일의 모든 체크 한 후 메인 스레드로 결과를 전송에서 약간의 지연에 의해 발생 정상). 그러나 구문 분석은 30 초에 갑자기 느려집니다. (한 번에 하나의 웹 작업자 만 사용하고 한 번에 두 개 이상의 작업자 스레드를 사용하지 않습니다.)

      지연이 이 아니며 메인으로 결과를 전송하는 데이 아닌 것으로 확인되었습니다. 스레드 postMessage(). 감속은 파서의 the tight loop에 있으며, 이는 전적으로 동기식입니다. 설명 할 수없는 이유 때문에 루프가 크게 느려지고 30 초가 지나면 느려집니다.

      하지만 이는 웹 작업자에게만 발생합니다. 위에서 보았 듯이 메인 스레드에서 같은 코드를 실행하면 매우 부드럽고 빠르게 실행됩니다.

      왜 이런 일이 발생합니까? 성능 향상을 위해 무엇을 할 수 있습니까? (필자는 누구나 파일의 모든 1,200 + 라인을 완전히 이해할 것으로 기대하지는 않는다. 만약 그렇게했다면, 그것은 훌륭하지만, 코드에서보다 웹 작업자와 더 관련이 있다는 느낌을 받는다. 스레드).

      시스템 : 16GB 메모리가 장착 된 Mac OS 10.9.4에서 Chrome 35를 실행 중입니다. 쿼드 코어 2.7GHz 인텔 코어 i7 (256KB L2 캐시 (코어 당) 및 L3 캐시 6MB) 파일 청크의 크기는 약 10MB입니다.

      업데이트 : 그냥 파이어 폭스 (30)에 그것을 시도하고 하지 경험 작업자 스레드에서 동일한 둔화했다 (하지만 메인 스레드에서 실행할 때 크롬보다 느렸다). 그러나 더 큰 파일 (약 1GB)로 동일한 실험을 시도하면 약 35-40 초 후에 상당한 속도 저하가 나타납니다 (보이는 것처럼 보입니다).

    +0

    간단한 i = i + 1 루프로 동일한 작업을보고 백만 회 반복마다 메시지를 인쇄합니다. 속도 저하는 Chrome에서 약 20 초 후, Firefox에서 12 초 후에 시작됩니다. 이게 뭐야? –

    답변

    12

    Tyler Ault suggested one possibility on Google+ 매우 유용한 것으로 판명되었습니다.

    그는 (평범한 '비동기 FileReader 대신) 작업자 스레드에서 FileReaderSync을 사용하면 가비지 수집을 할 수있는 기회가 제공되지 않는다고 추측했습니다.

    은 (직관적으로 성능 단계 뒤로 것 같다) 비동기 FileReader를 사용하는 작업자 스레드를 변경하면 나는 그것이 것으로 기대 바로 여기서 다시 단지 37초까지의 과정을 가속.

    나는 아직 다시 타일러에서 못 들었 내가 가비지 컬렉션이 범인 왜 이해 완전히 모르겠지만, 뭔가에 대한 FileReaderSync 코드를 늦추고 크게했다.

    +0

    그래서 동일한 문제가 발생하지만 가비지 수집은 힙 메모리를 복구하지 못하도록하는 약속 체인으로 인해 발생하지 않습니다. 스냅 샷을 사용하면 fileReader가 힙이 최대로되었을 때 속도가 느려지는 것을 알 수 있으며 가비지 수집기가 더 많은 공간을 확보 할 때까지 기다리는 동안 크롤링합니다. – James

    +0

    아마도 가비지 수집은 이벤트 루프로 돌아 가면 발생할 수 있습니다. –

    2

    실행중인 하드웨어는 무엇입니까? CPU에 문제가있는 캐시를 실행 중일 수 있습니다. 예를 들어 CPU 캐시가 코어 당 1MB 인 경우 (예를 들어) 캐시에서 데이터를 계속 사용하려고 시도하면 (캐시 ​​누락) 속도가 느려집니다. 이것은 MT 시스템에서 매우 일반적입니다. 이는 IO 전송에서도 일반적입니다. 또한 이러한 시스템은 스레드 컨텍스트에 대해 일부 OS 오버 헤드를 갖는 경향이 있습니다. 따라서 많은 스레드가 생성되면 스레드가 '수행중인 작업'보다 컨텍스트를 관리하는 데 더 많은 시간을 소비 할 수 있습니다. 아직 코드를 보지 못했기 때문에 벗어날 수 있습니다.하지만 내 추측은 응용 프로그램이 수행하는 작업으로 인한 메모리 문제입니다. :)

    오. 어떻게 고치는 지. 실행 블록을 하드웨어와 일치하는 작은 단일 청크로 만듭니다. 한 번에 사용중인 스레드의 양을 최소화하십시오 - 하드웨어에있는 코어의 2 ~ 3 배를 유지하도록하십시오 (실제로 어떤 종류의 하드웨어를 사용하는지에 따라 다릅니다). 희망이 도움이됩니다.

    +0

    이러한 아이디어에 감사드립니다. 내 질문에 시스템 사양을 추가했습니다. 청크 크기를 줄이는 것은 흥미로운 아이디어입니다. 나는 10MB 청크 대신에 2MB 덩어리로 시험해 보았고 마지막 백만 열 (약 30 초 만에 다시)에서 상당한 속도 감소를 발견했다. 그리고 그것은 (내가 궁금해하는 한) 웹 작업자 만 실행합니다. 불행히도 우리는 여전히 설명을 찾아야합니다. – Matt