기억을 통해 기능의 집행 속도를 높이다

오늘 나는 무엇이 기억화되었는지, 그리고 무엇이 용례 장면의 예일 수 있는지 설명해 보려고 한다.나는 어떤 방면에서도 전문가가 아니다. 나는 단지 열정적인 사람일 뿐이다. 너희들 중 일부와 같다.나는 공교롭게도 이 문제에 부딪혔으니, 나는 이 문제에 대한 나의 견해를 나누고 싶다.만약 내가 본문에서 어떤 잘못이 있다면, 아래의 평론 부분에서 나에게 알려주십시오.우리는 모두 다른 사람의 정확성에서 이익을 얻을 수 있다.

해시시계 같아.
기억은 함수의 집행 시간을 줄이는 방법의 하나다.그것은 모든 함수 호출의 결과를 저장함으로써 실현된다.마치 해시표 같다.이전과 같은 매개 변수 호출 함수를 사용하려고 시도하면, 전체 계산에 들어가지 않고 캐시 결과만 되돌려줍니다.물론 함수가 예상한 결과를 되돌리는 데 걸리는 시간을 줄이는 데 도움이 된다.
예를 들어, 우리가 add 라는 함수를 가지고 있다고 가정하자.그것은 두 개의 매개 변수를 숫자로 덧붙여야 한다. 이런 함수의 정의는 바로
"use strict";

function add(number1, number2) {
    return number1 + number2;
}
우리는 현재 우리의 함수를 사용하고 숫자를 추가할 수 있다.
add(1, 2); // 3
add(3, 4); // 7
add(1, 2); // 3

참조 투명도
여기에 주의해야 할 두 가지 일이 있다.첫째, 우리의 함수는 순함수다.기억이 어떻게 작동하는지 이해하기 위해서는 중요한 개념이다.순수함수는 부작용이 없는 함수로 같은 매개 변수에 대해 항상 같은 결과를 되돌려주고 참고투명도라고도 부른다.
부작용은 우리의 함수를 완전하지 못하게 하고 결과를 예측할 수 없게 하여 투명한 특성을 인용하지 못하게 한다.투명성을 인용하는 것은 이러한 사실이다. 같은 매개 변수에 대해 항상 같은 결과의 함수를 되돌려주고 코드의 어느 곳에서든 그 결과로 바꿀 수 있다.이것은 이 두 단락의 코드가 같다는 것을 의미한다.
console.log(add(1, 2) === 3);
console.log(add(3, 4) === 7);
console.log(add(1, 2) === 3);
console.log(3 === 3);
console.log(7 === 7);
console.log(3 === 3);
주어진 매개 변수에 대해 우리는 항상 같은 결과를 얻는다고 확신하는 이상, 비싼 덧셈 과정을 벗어나 사전 (또는 자바스크립트의 대상) 을 사용하여 결과를 되돌려주고 편지 수를 가속화할 수 있도록 함수를 완전히 다시 쓸 수 있다.
"use strict";

function add(...parameters) {
    const cache = {
        [[1, 2]]: 3,
        [[3, 4]]: 7,
        [[5, 6]]: 11
    }; 

    return cache[parameters];
}

console.log(add(1, 2) === 3);  // true
console.log(add(3, 4) === 7);  // true
console.log(add(5, 6) === 11); // true

캐시를 통해 얻을 수 있는 이점
그러나 캐시되지 않은 두 개의 숫자를 추가하려고 할 때, 우리는 스스로 계산해야 한다.이 캐시된 숫자들을 통계 연구에서 얻은 숫자로 상상하면 가장 많이 추가된 숫자를 나타낸다.그 밖에 우리는 가장 자주 사용하는 숫자를 캐시하고 나머지 숫자를 스스로 계산해서 많은 이익을 얻을 수 있다.
"use strict";

function add(...parameters) {
    const cache = {
        [[1, 2]]: 3,
        [[3, 4]]: 7,
        [[5, 6]]: 11
    }; 

    if (parameters in cache) {
        return cache[parameters];
    }

    return parameters[0] + parameters[1];
}

console.log(add(1, 2) === 3);   // true (cached)
console.log(add(3, 4) === 7);   // true (cached)
console.log(add(5, 6) === 11);  // true (cached)
console.log(add(7, 8) === 15);  // true (computed)
보시다시피 캐시된 숫자는 우리가 예상한 매개 변수입니다.나머지는 모두 평소와 같이 계산한다.하지만 불편하다.사실 이 외에도 가장 자주 사용하는 숫자도 끊임없이 변화하고 있으며 처음부터 큰 캐시가 있는 것은 매우 비효율적이다.가장 좋은 것은 우리의 함수를 사용한 후에 캐시에 데이터를 제공하는 것이다.캐시를 저장하는 전역 변수처럼이것이 바로 회고록의 의미다.
좀 더 고급스러운 용례 장면을 사용하자.예를 들면 피보나치 서열.만약 네가 수학에 대해 안심하지 못한다면, 걱정하지 마라. 왜냐하면 우리는 둘이기 때문이다.이것은 기억 함수에서 어떻게 이익을 얻을 수 있는지 보여주는 좋은 예이다.나는 피보나치 서열이 지수가 증가하는 족보라고 생각한다.
다음은 이 함수의 귀속 정의이다.
"use strict";

function fibonacci(number) {
    if (number === 1) {
        return 1;
    }

    if (number < 1) {
        return 0;
    }

    return fibonacci(number - 1) + fibonacci(number - 2);
}
이것은 매번 우리가 계산N-1N-2의 피보나치 서열을 합쳐서 그것들을 더하는 것을 의미한다.정지 조건은 우리가 서열0th1st의 개수에 도달했을 때 서열이 01인 것을 알 수 있다.그러나 이것은 귀속 함수이고 피보나치 서열의 계산 방식을 고려하면 같은 매개 변수로 여러 번 호출될 가능성이 높다.서열 제40의 개수에 필요한 시간을 계산해 봅시다.
const start = new Date().getTime();

fibonacci(40);

const stop = new Date().getTime();

console.log(`Fibonacci(40) executed in ${stop - start}ms.`);
// Fibonacci(40) executed in 1966ms.

믿기 어렵다
이제 memonization을 사용해서 계산해 봅시다. (나는 1분 안에 실현된 세부 사항을 설명할 것입니다.)
let start = new Date().getTime();

console.log(fibonacci(40));
// 102334155

let stop = new Date().getTime();

console.log(`fibonacci(40) executed in ${stop - start}ms.`);
// Fibonacci(40) executed in 1966ms.

start = new Date().getTime();

console.log(memoizedFibonacci(1250));
// 7.674768958056894e+260

stop = new Date().getTime();

console.log(`memoizedFibonacci(1250) executed in ${stop - start}ms.`);
// memoizedFibonacci(1250) executed in 1ms.
다음은 memoizedFibonacci 함수의 실현이다.
const memoizedFibonacci = (function() {
    const cache = {};

    return function $fibonacci(number) {
        if (number === 1) {
            return 1;
        }

        if (number < 1) {
            return 0;
        }

        if (number in cache) {
            return cache[number];
        }

        const result = $fibonacci(number - 1) + $fibonacci(number - 2);

        cache[number] = result;

        return result;
    };
})();
나는 이것이 믿기 어렵다는 것을 인정한다.그래서 나는 네가 스스로 테스트하는 것을 건의한다. 왜냐하면 연습은 가장 좋은 학습 방식이기 때문이다.Repl It와 같은 온라인 플랫폼에서 테스트를 수행하는 경우 서버에서 계산하는 데 시간이 더 걸릴 수 있으므로 최적화되지 않은 피포나치 버전에 작은 값을 사용해 보십시오.
나도 잠시 의심했다. (나는 어떤 로그 기록도 사용하지 않았기 때문에 이 글을 쓸 때 그것을 추가했다.)하지만 내가 이렇게 많은 숫자를 얻은 이후로 여기는 아무런 문제가 없다.사실, Infinity 값을 얻기 전에 나는 내 컴퓨터에서 이 값을 초과할 수 없다.노드가 정확한지 확실하지 않기 때문이다.js는 이 숫자를 계산할 수 없거나 함수에 문제가 있기 때문에 가장 의미 있고 높은 값을 검색해서 보여 줍니다.
그러나 이것은 우리가 작성한 함수의 원시 정의보다 훨씬 빠를 뿐만 아니라, 우리는 더 높은 값을 사용했다.이 모든 것은 폐쇄와 물체 덕분이다.이렇게 간단해!
클로즈업에 익숙하지 않다면, 이 값을 전역적으로 저장하는 방법으로 간주하고, 이 값을 우리의 함수에만 사용할 수 있도록 유지할 수 있습니다. (이것은 외부 세계가 이 값을 수정하지 않는다는 것을 의미하며, 코드의 다른 모듈에 의해 캐시가 손상되지 않도록 보장할 수 있습니다.)
또한 IIFE (즉시 호출되는 함수 표현식) 를 사용하여 캐시를 클립된 범위 내에 보존합니다.상술한 목적과 같다.만약 네가 이 용어들에 대해 익숙하지 않다면, 늘 잊지 말고, 빨리 검색하기만 하면 더욱 많은 것을 알 수 있다.
그러나 이런 상황에서 기억 기능이 더욱 강한 것은 현재 우리는 서열 n개수Infinity의 값을 성공적으로 계산했기 때문에 우리는 그것을 계산할 필요가 없다. 왜냐하면 그것은 캐시이기 때문이다.다음에 매개 변수 1250 호출 memoizedFibonacci 함수를 사용하면 대상과 비교하기만 하면 됩니다.다른 건 없어요.

결론
요컨대, 기억은 기능 프로그래밍이라는 더 큰 계획의 일부분이다.투명성을 인용하면 우리는 신뢰할 수 있는 캐시를 가지고 같은 매개 변수에 대한 후속 호출을 가속화할 수 있다.이것은 우리가 최소한 매개 변수 집합의 값을 계산해야 하기 때문에 신기한 방법이 아니다.그러나 중용성과 인식 분해가 가능한 세계에서 그것은 정말 유용하다. 우리는 한 개의 값을 한 번 이상 계산할 필요가 없다.

좋은 웹페이지 즐겨찾기