"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > JSON.stringify와 경쟁 - 사용자 정의를 구축하여

JSON.stringify와 경쟁 - 사용자 정의를 구축하여

2024-08-20에 게시됨
검색:318

Competing with JSON.stringify - by building a custom one

이것은 내 친구와 재귀에 관해 토론하는 동안 나온 것입니다.
를 빌드하면 어떨까요? 재귀 프로그래밍 연습으로 Javascript JSON.stringify 메소드를 사용하시겠습니까? 정말 좋은 것 같아요
아이디어.

첫 번째 버전의 초안을 빠르게 작성했습니다. 그리고 그것은 끔찍하게 수행되었습니다!
필요한 시간은 표준 JSON.stringify의 약 4배였습니다.

첫 번째 초안

function json_stringify(obj) {
  if (typeof obj == "number" || typeof obj == "boolean") {
    return String(obj);
  }

  if (typeof obj == "string") {
    return `"${obj}"`;
  }

  if (Array.isArray(obj)) {
    return "["   obj.map(json_stringify).join(",")   "]";
  }

  if (typeof obj === "object") {
    const properties_str = Object.entries(obj)
      .map(([key, val]) => {
        return `"${key}":${json_stringify(val)}`;
      })
      .join(",");
    return "{"   properties_str   "}";
  }
}

다음을 실행하면 json_stringify가 다음과 같이 작동하는 것을 볼 수 있습니다.
예상되는.

const { assert } = require("console");
const test_obj = {
  name: "John Doe",
  age: 23,
  hobbies: ["football", "comet study"]
};

assert(json_stringify(test_obj) === JSON.stringify(test_obj))

더 많은 시나리오를 테스트하고 여러 번 실행하여
스크립트가 실행되면 간단한 테스트 스크립트를 만들었습니다!

간단한 테스트 스크립트

function validity_test(fn1, fn2, test_values) {
  for (const test_value of test_values) {
    assert(fn1(test_value) == fn2(test_value));
  }
}

function time(fn, num_runs = 1, ...args) {
  const start_time = Date.now()

  for (let i = 0; i 


이를 실행하면 다음과 같은 타이밍을 얻습니다.

Testing 1000 times
    Std lib JSON.stringify() took 5 ms
    Custom json_stringify() took 20 ms
Testing 10000 times
    Std lib JSON.stringify() took 40 ms
    Custom json_stringify() took 129 ms
Testing 100000 times
    Std lib JSON.stringify() took 388 ms
    Custom json_stringify() took 1241 ms
Testing 1000000 times
    Std lib JSON.stringify() took 3823 ms
    Custom json_stringify() took 12275 ms

시스템에 따라 다르게 실행될 수 있지만 소요되는 시간의 비율은
std JSON.strngify에서 사용자 정의 json_stringify의 값은
정도여야 합니다. 1:3 - 1:4

흥미로운 경우에도 다를 수 있습니다.
에 대해 자세히 알아보려면 계속 읽어보세요. 저것!

성능 향상

가장 먼저 고칠 수 있는 것은 지도 기능의 사용입니다.
를 생성합니다. 이전 배열의 새 배열. 객체의 경우에는
배열을 생성합니다. 객체 항목을 포함하는 배열에서 JSON으로 문자열화된 객체 속성입니다.

배열 요소의 문자열화에서도 비슷한 일이 발생합니다.

배열의 요소나 객체의 항목을 반복해야 합니다! 하지만
JSON 문자열화된 부분을 결합하기 위해 다른 배열 생성을 건너뛸 수 있습니다.

업데이트된 버전은 다음과 같습니다. (간결성을 위해 변경된 부분만 표시)

function json_stringify(val) {
  if (typeof val === "number" || typeof val === "boolean") {
    return String(val);
  }

  if (typeof val === "string") {
    return `"${val}"`;
  }

  if (Array.isArray(val)) {
    let elements_str = "["

    let sep = ""
    for (const element of val) {
      elements_str  = sep   json_stringify(element)
      sep = ","
    }
    elements_str  = "]"

    return elements_str
  }

  if (typeof val === "object") {
    let properties_str = "{"

    let sep = ""
    for (const key in val) {
      properties_str  = sep   `"${key}":${json_stringify(val[key])}`
      sep = ","
    }
    properties_str  = "}"

    return properties_str;
  }
}

이제 테스트 스크립트의 출력은 다음과 같습니다.

Testing 1000 times
        Std lib JSON.stringify() took 5 ms
        Custom json_stringify() took 6 ms
Testing 10000 times
        Std lib JSON.stringify() took 40 ms
        Custom json_stringify() took 43 ms
Testing 100000 times
        Std lib JSON.stringify() took 393 ms
        Custom json_stringify() took 405 ms
Testing 1000000 times
        Std lib JSON.stringify() took 3888 ms
        Custom json_stringify() took 3966 ms

이제 훨씬 좋아 보입니다. 우리의 사용자 정의 json_stringify는 단 3ms만 소요됩니다
JSON.stringify 이상으로 깊이 중첩된 객체를 10,000번 문자열화합니다.
완벽하지는 않지만 허용되는 지연입니다.

더 짜내??

현재 지연은 모든 문자열 생성 및 연결로 인해 발생할 수 있습니다.
그런 일이 일어나고 있습니다. elements_str = sep json_stringify(element)
를 실행할 때마다 우리는 3개의 문자열을 연결하고 있습니다.

문자열을 연결하려면 비용이 많이 듭니다.

  1. 결합된 전체 문자열에 맞는 새 문자열 버퍼 생성
  2. 새로 생성된 버퍼에 개별 문자열을 복사합니다.

버퍼를 직접 사용하고 거기에 데이터를 직접 작성하면 다음과 같은 결과를 얻을 수 있습니다.
성능 개선. 큰 버퍼(예: 80자)를 만들 수 있으므로
그런 다음 버퍼가 부족해지면 80자를 더 수용할 수 있도록 새 버퍼를 만듭니다.

데이터의 재할당/복사를 완전히 피할 수는 없지만,
이러한 작업을 줄입니다.

또 다른 지연 가능성은 재귀 프로세스 자체입니다! 구체적으로
시간이 걸리는 함수 호출. 함수 호출 json_stringify(val)
를 고려해 보세요. 매개변수가 하나뿐입니다.

함수 호출 이해

단계는 다음과 같습니다.

  1. 반환 주소를 스택에 푸시
  2. 인수 참조를 스택에 푸시
  3. 호출된 함수에서
    1. 스택에서 매개변수 참조를 팝합니다.
    2. 스택에서 반환 주소를 팝합니다.
    3. 반환 값(문자열화된 부분)을 스택에 푸시합니다.
  4. 호출 기능에서
    1. 스택에서 함수가 반환한 값을 꺼냅니다.

이 모든 작업은 함수 호출이 발생하도록 하기 위해 발생하며 이로 인해 CPU가 추가됩니다.
소송 비용.

json_stringify의 비재귀 알고리즘을 생성하면 이러한 모든 작업이 수행됩니다.
위에 나열된 함수 호출(해당 호출 횟수의 곱)은
입니다. 없음으로 줄였습니다.

이는 향후 시도가 될 수 있습니다.

NodeJs 버전 차이

여기서 마지막으로 주목해야 할 사항이 있습니다. 테스트 스크립트의 다음 출력을 고려하세요

Testing 1000 times
        Std lib JSON.stringify() took 8 ms
        Custom json_stringify() took 8 ms
Testing 10000 times
        Std lib JSON.stringify() took 64 ms
        Custom json_stringify() took 51 ms
Testing 100000 times
        Std lib JSON.stringify() took 636 ms
        Custom json_stringify() took 467 ms
Testing 1000000 times
        Std lib JSON.stringify() took 6282 ms
        Custom json_stringify() took 4526 ms

맞춤형 json_stringify가 NodeJs 표준보다 성능이 더 좋았나요?
JSON.stringify???

그렇습니다! 하지만 이는 NodeJs의 이전 버전(v18.20.3)입니다. 알고 보니
이 버전(및 그 이하 버전)은 맞춤 제작된 json_stringify가 작동합니다
표준 라이브러리보다 빠릅니다!

이 기사에 대한 모든 테스트(이 마지막 기사 제외)는
로 수행되었습니다. 노드 v22.6.0

JSON.stringify의 성능이 v18에서 v22로 향상되었습니다. 정말 대단해요

우리 스크립트가 NodeJs v22에서 더 나은 성능을 발휘했다는 점도 중요합니다.
즉, NodeJ가 런타임의 전반적인 성능도 향상했다는 의미입니다.
아마도 기본 V8 엔진 자체에 업데이트가 발생했을 수 있습니다.

글쎄, 이것은 나에게 즐거운 경험이었습니다. 그리고 그것이
를 위한 것이기를 바랍니다. 너도. 그리고 이 모든 즐거움 속에서 우리는 한두 가지를 배웠습니다!

계속 구축하고 계속 테스트하세요!

릴리스 선언문 이 기사는 https://dev.to/riturajborpujari/competing-with-jsonstringify-by-building-a-custom-one-53l5?1에서 복제됩니다. 침해가 있는 경우, [email protected]에 연락하여 삭제하시기 바랍니다. 그것
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3