캐싱 데코레이터

내 상상력이 제한되어 있기 때문에 무거운 계산을 수행하는 클래스가 있다고 상상해 봅시다. 계산을 수행하는 클래스를 제안하겠습니다(댓글에 더 멋진 것을 소개할 수 있으므로 부끄러움을 멈출 수 있습니다).

class CountdownCalculator {
  public countDown(n: number): number {
    let count = 0;
    while (count < n) {
      count += 1;
    }
    return count;
  }
}
const countdownCalculator = new CountdownCalculator();


따라서 우리가 전달하는 숫자가 클수록 작동하는 시간이 더 길어집니다. 어느 시점에서 우리는 그 결과를 메모하기를 원할 수 있습니다. 그래서 메서드가 이전에 계산한 숫자를 받는 경우에는 단순히 결과를 즉시 반환합니다.

메서드를 몇 번 호출하고 어떻게 진행되는지 살펴보겠습니다.

for (let x = 0; x++ <= 1;) {
  const start = performance.now();
  const result = countdownCalculator.countDown(500000000);
  const end = performance.now();

  console.log(`Result is: ${result}. Execution time of the first invocation: ${end - start} ms`);
}

// [LOG]: "Result is: 500000000. Execution time of the first invocation: 157.19999992847443 ms" 
// [LOG]: "Result is: 500000000. Execution time of the first invocation: 156 ms"


메서드/클래스 자체를 수정하여 인수를 메모하거나 TypeScript에서 제공하는 멋진 데코레이터 기능을 사용하고 데코레이터를 만들 수 있습니다.

function memoize(
  target: unknown,
  propertyKey: string,
  descriptor: PropertyDescriptor
): void {
  const cachedResults = new Map<number, number>();

  const originalMethod = descriptor.value;

  descriptor.value = function (...args: unknown[]) {
    const num = args[0] as number;
    if (cachedResults.has(num)) {
      return cachedResults.get(num)
    }
    const result = originalMethod.apply(this, args);
    cachedResults.set(num, result);
    return result;
  };
}


구현은 순진하고 단순합니다. 즉, 인수로 전달되는 여러 인수 또는 객체와 같은 문제를 처리하지 않습니다. 하지만 어쨌든.

이제 우리는 캐싱 데코레이터로 구피 메서드를 장식하고 작동하는 것을 볼 수 있습니다(전체 코드를 사용할 수 있습니다in the sandbox btw ).

function memoize(
  target: unknown,
  propertyKey: string,
  descriptor: PropertyDescriptor
): void {
  const cachedResults = new Map<number, number>();

  const originalMethod = descriptor.value;

  descriptor.value = function (...args: unknown[]) {
    const num = args[0] as number;
    if (cachedResults.has(num)) {
      return cachedResults.get(num)
    }
    const result = originalMethod.apply(this, args);
    cachedResults.set(num, result);
    return result;
  };
}

class CountdownCalculator {
  @memoize
  public countDown(n: number): number {
    let count = 0;
    while (count < n) {
      count += 1;
    }
    return count;
  }
}

const countdownCalculator = new CountdownCalculator();

for (let x = 0; x++ <= 1;) {
  const start = performance.now();
  const result = countdownCalculator.countDown(500000000);
  const end = performance.now();

  console.log(`Result is: ${result}. Execution time of the first invocation: ${end - start} ms`);
}

// [LOG]: "Result is: 500000000. Execution time of the first invocation: 156.40000009536743 ms" 
// [LOG]: "Result is: 500000000. Execution time of the first invocation: 0 ms" 


멋지다, 응? :디

좋은 웹페이지 즐겨찾기