JavaScript를 사용하기 전에는 이미 C, C++, C#에 익숙했습니다. 많은 C/C++ 개발자와 마찬가지로 JavaScript에 대한 나의 첫인상은 좋지 않았습니다. 이 기사에서는 주로 JavaScript 배열의 발전과 성능 분석을 소개합니다. 이 기사에서는 메모리, 최적화, 구문 차이, 성능 및 최근 발전에 대해 자세히 설명합니다. 도움이 필요한 친구들이 참고할 수 있고, 모두에게 도움이 되기를 바랍니다.
배열이 주된 이유 중 하나입니다. JavaScript 배열은 연속적이지 않으며 해시 맵이나 사전처럼 구현됩니다. 나는 이것이 약간 B 수준 언어라고 생각하며 배열 구현은 단순히 부적절합니다. 그 이후로 JavaScript와 그에 대한 나의 이해가 많이 바뀌었습니다.
JavaScript 배열이 실제 배열이 아닌 이유
JavaScript에 대해 이야기하기 전에 먼저 Array가 무엇인지부터 살펴보겠습니다.
배열은 특정 값을 보유하는 데 사용되는 연속적인 메모리 위치 시퀀스입니다. "연속적"(또는 연속적)이라는 강조점을 주목하는 것이 중요합니다.
위 그림은 배열이 메모리에 저장되는 방식을 보여줍니다. 이 배열은 4개의 요소를 보유하며 각 요소는 4바이트입니다. 전체적으로 16바이트의 메모리 영역을 차지합니다.
tinyInt arr[4];를 선언한다고 가정하면 할당된 메모리 영역의 주소는 1201부터 시작합니다. arr[2]를 읽으려면 수학적 계산을 통해 arr[2]의 주소만 얻으면 됩니다. 1201 + (2 X 4)를 계산하려면 1209부터 직접 읽기 시작하세요.
JavaScript의 데이터는 연결된 목록과 같은 다양한 데이터 구조를 사용하여 구현할 수 있는 해시 맵입니다. 따라서 JavaScript var arr = new Array(4)에서 배열을 선언하면 컴퓨터는 위에 표시된 것과 유사한 구조를 생성합니다. 프로그램이 arr[2]를 읽어야 하는 경우 1201부터 시작하는 주소 지정을 순회해야 합니다.
위의 빠른 JavaScript 배열과 실제 배열의 차이점. 분명히 수학적 계산은 연결 목록을 순회하는 것보다 빠릅니다. 이는 긴 배열의 경우 특히 그렇습니다.
JavaScript 배열의 진화
친구들이 사준 256MB 메모리 컴퓨터가 너무 부러웠던 시절을 기억하시나요? 오늘날 8GB RAM은 어디에나 있습니다.
마찬가지로 JavaScript 언어도 많이 발전했습니다. V8과 SpiderMonkey부터 TC39와 웹 사용자의 증가에 이르기까지 엄청난 노력으로 인해 JavaScript는 세계적 수준의 필수품이 되었습니다. 대규모 사용자 기반이 있으면 성능 개선은 당연히 어려운 요구 사항입니다.
사실 최신 JavaScript 엔진은 배열이 동종인 경우(모든 요소가 동일한 유형인 경우) 배열에 연속 메모리를 할당합니다. 좋은 프로그래머는 JIT(Just-In-Time 컴파일러)가 c 컴파일러 스타일 계산을 사용하여 요소를 읽을 수 있도록 항상 배열이 동종인지 확인합니다.
그러나 다른 유형의 요소를 동종 배열에 삽입하려는 경우 JIT는 전체 배열을 분해하고 이전 방식으로 다시 만듭니다.
그래서 코드가 나쁘지 않다면 JavaScript Array 객체는 배후에서 실제 배열로 유지되며 이는 현대 JS 개발자에게 매우 중요합니다.
또한 ES2015/ES6에 이어 어레이도 더욱 진화했습니다. TC39는 형식화된 배열(Typed Arrays)을 도입하기로 결정하여 ArrayBuffer를 갖게 되었습니다.
ArrayBuffer는 우리가 마음대로 작동할 수 있도록 연속 메모리를 제공합니다. 그러나 직접적으로 메모리를 조작하는 것은 여전히 너무 복잡하고 낮은 수준입니다. 그래서 ArrayBuffer를 처리하는 뷰가 있습니다. 이미 몇 가지 보기를 사용할 수 있으며 앞으로 더 많은 보기가 추가될 예정입니다.
var buffer = new ArrayBuffer(8); var view = new Int32Array(buffer); view[0] = 100;
WebGL 이후 고성능의 효율적인 형식 배열이 도입되었습니다. WebGL 작업자는 바이너리 데이터를 효율적으로 처리하는 방법이라는 큰 성능 문제에 직면합니다. 또는 SharedArrayBuffer를 사용하여 여러 웹 작업자 프로세스 간에 데이터를 공유하여 성능을 향상시킬 수 있습니다.
간단한 해시 맵에서 이제 SharedArrayBuffer까지, 정말 멋지죠?
기존 스타일 배열과 형식화된 배열: 성능
우리는 이전에 JavaScript 배열의 발전에 대해 논의했습니다. 이제 최신 배열이 얼마나 많은 이점을 가져올 수 있는지 테스트해 보겠습니다. 다음은 Node.js 8.4.0을 사용하여 Mac에서 실행한 몇 가지 마이크로 테스트 결과입니다.
이전 스타일 배열: Insert
var LIMIT = 10000000; var arr = new Array(LIMIT); console.time("Array insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("Array insertion time");
소요 시간: 55ms
Typed Array:插入 var LIMIT = 10000000; var buffer = new ArrayBuffer(LIMIT * 4); var arr = new Int32Array(buffer); console.time("ArrayBuffer insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("ArrayBuffer insertion time");
소요 시간: 52ms
문지르세요, 무엇을 볼 수 있나요? 이전 스타일의 배열과 ArrayBuffer의 성능은 동일합니까? 아니 아니 아니. 앞서 언급했듯이 최신 컴파일러는 내부적으로 동일한 요소 유형의 기존 배열을 메모리 연속 배열로 변환할 수 있을 만큼 똑똑합니다. 이것이 바로 첫 번째 예의 경우입니다. new Array(LIMIT)를 사용함에도 불구하고 해당 어레이는 여전히 최신 어레이로 존재합니다.
그런 다음 첫 번째 예를 수정하고 배열을 이종 배열(요소 유형이 완전히 일관되지 않음)로 변경하여 성능 차이가 있는지 확인합니다.
旧式数组:插入(异构) var LIMIT = 10000000; var arr = new Array(LIMIT); arr.push({a: 22}); console.time("Array insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("Array insertion time");
시간: 1207ms
3행에서 변경이 발생하며, 배열을 이종 유형으로 변경하는 명령문을 추가합니다. 나머지 코드는 동일하게 유지됩니다. 성능 차이는 22배 느리게 나타납니다.
이전 스타일 배열: 읽기
var LIMIT = 10000000; var arr = new Array(LIMIT); arr.push({a: 22}); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } var p; console.time("Array read time"); for (var i = 0; i < LIMIT; i++) { //arr[i] = i; p = arr[i]; } console.timeEnd("Array read time");
시간: 196ms
Typed Array:读取 var LIMIT = 10000000; var buffer = new ArrayBuffer(LIMIT * 4); var arr = new Int32Array(buffer); console.time("ArrayBuffer insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.time("ArrayBuffer read time"); for (var i = 0; i < LIMIT; i++) { var p = arr[i]; } console.timeEnd("ArrayBuffer read time");
시간: 27ms
결론
형 배열의 도입은 JavaScript 개발에 있어서 큰 진전입니다. Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, 이들은 네이티브 엔디안(네이티브와 동일)을 사용하는 형식화된 배열 뷰입니다. DataView를 사용하여 사용자 정의 보기 창을 만들 수도 있습니다. 앞으로 ArrayBuffer를 쉽게 조작하는 데 도움이 되는 DataView 라이브러리가 더 많아지기를 바랍니다.
JavaScript 배열의 발전은 매우 훌륭합니다. 이제 그들은 빠르고 효율적이며 강력하고 메모리 할당에 있어 충분히 똑똑합니다.
위 내용은 JavaScript 배열 발전 및 성능 분석 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!