💨

Momento Cache Increment API について

2023/11/19に公開

先日アップしたSorted Setsに関する記事で、アイテムの要素を増やしたり減らしたりするsortedSetIncrementScoreを紹介しました。コレクションデータ型ではこの機能をその萎えているのでSorted Setsだけでしたが、標準アイテムでもIncrementという機能が存在しています。
https://zenn.dev/momentobigfun/articles/18fe0f1d2cec19

通常アイテム内の要素に対して、例えば1を足すとした場合
1.アイテムの取り出し
(数字計算処理)
2.アイテムの書き込み
という2Stepなのに対して、Incrementを用いることで1つのAPI Callで数字を減らしたり増やしたりできます。

さっそくやってみる

test.js
// Declare the Momento SDK library
const {
    Configurations,
    CacheClient, CredentialProvider,
    CacheIncrement, 
} = require('@gomomento/sdk');

// Declate the dotenv library
const dotenv = require('dotenv');

// Run the config function to bring in the .env file
dotenv.config();

// Creates the Momento cache client object
async function createCacheClient() {
    return await CacheClient.create({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromEnvironmentVariable({
            environmentVariableName: 'MOMENTO_API_KEY',
        }),
        defaultTtlSeconds: 600,
    });
}

// A simple function that calls all functions in order. You probably want more error handling.
async function run() {
    const cacheClient = await createCacheClient();
    await cacheClient.set('demo-cache', 'test-key', '10');
    const result = await cacheClient.increment('demo-cache', 'test-key', 1);
    if (result instanceof CacheIncrement.Success) {
        console.log(`Key 'test-key' incremented successfully. New value in key test-key: ${result.valueNumber()}`);
    } else if (result instanceof CacheIncrement.Error) {
        throw new Error(
            `An error occurred while attempting to increment the value of key 'test-key' from cache 'test-cache': ${result.errorCode()}: ${result.toString()}`
        );
    }
}
run();
await cacheClient.set('demo-cache', 'test-key', '10');
const result = await cacheClient.increment('demo-cache', 'test-key', 1);

'demo-cache'というキャッシュ空間に対して、'test-key'というキーで'10'という値を持ったアイテムを書き込みます。その後incrementで1足しています。
通常10は[]Byte型として取り扱われますが、incrementを用いた場合は数値として処理されます。

Key 'test-key' incremented successfully. New value in key test-key: 11

1の代わりに-1を指定することで数字を減らすことが出来ます。

const result = await cacheClient.increment('demo-cache', 'test-key', -1);
Key 'test-key' incremented successfully. New value in key test-key: 9

どれぐらい早くなるのか?

incrementを用いた場合、通常のGetSetと比べてどのぐらい早くなるのでしょうか。
やってみます。まずは上記のコードを100回実行するように改造します。

100increments.js
// Declare the Momento SDK library
const {
    Configurations,
    CacheClient, CredentialProvider,
    CacheIncrement,
} = require('@gomomento/sdk');

// Declate the dotenv library
const dotenv = require('dotenv');

// Run the config function to bring in the .env file
dotenv.config();

// Creates the Momento cache client object
async function createCacheClient() {
    return await CacheClient.create({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromEnvironmentVariable({
            environmentVariableName: 'MOMENTO_API_KEY',
        }),
        defaultTtlSeconds: 600,
    });
}

global.result=null;
// A simple function that calls all functions in order. You probably want more error handling.
async function run() {
    const cacheClient = await createCacheClient();

    await cacheClient.set('demo-cache', 'test-key', '10');
    const begin = performance.now();
    for (let i = 0; i < 100; i++) {
        global.result= await cacheClient.increment('demo-cache', 'test-key', 1);
    }
    const end = performance.now();
    console.log(end-begin);

    if (global.result instanceof CacheIncrement.Success) {
        console.log(`Key 'test-key' incremented successfully. New value in key test-key: ${result.valueNumber()}`);
    } else if (global.result instanceof CacheIncrement.Error) {
        throw new Error(
            `An error occurred while attempting to increment the value of key 'test-key' from cache 'test-cache': ${result.errorCode()}: ${result.toString()}`
        );
    }
}
run();

クライアントがWindows環境(東京近辺)でMomentoキャッシュがAWS 東京リージョンの場合、おおよそ8ms前後が1アイテムあたりの処理時間になります。

819.526200003922
Key 'test-key' incremented successfully. New value in key test-key: 110

では次に通常のGetSetをやってみます。

getset100.js
// Declare the Momento SDK library
const {
    Configurations,
    CacheClient, CredentialProvider,
    CacheIncrement, CacheGet,
} = require('@gomomento/sdk');

// Declate the dotenv library
const dotenv = require('dotenv');

// Run the config function to bring in the .env file
dotenv.config();

// Creates the Momento cache client object
async function createCacheClient() {
    return await CacheClient.create({
        configuration: Configurations.Laptop.v1(),
        credentialProvider: CredentialProvider.fromEnvironmentVariable({
            environmentVariableName: 'MOMENTO_API_KEY',
        }),
        defaultTtlSeconds: 600,
    });
}

// A simple function that calls all functions in order. You probably want more error handling.
async function run() {
    const cacheClient = await createCacheClient();

    await cacheClient.set('demo-cache', 'test-key', '10');

    const begin = performance.now();
    for (let i = 0; i < 100; i++) {
        const result = await cacheClient.get('demo-cache', 'test-key');
        let value = result.valueString()
        let number = parseInt(value);
        number = number + 1;
        value = String(number);
        await cacheClient.set('demo-cache', 'test-key', value);
    }
    const end = performance.now();
    console.log(end-begin);
    const result2 = await cacheClient.get('demo-cache', 'test-key');

    if (result2 instanceof CacheGet.Hit) {
        console.log(`Retrieved value for key 'test-key': ${result2.valueString()}`);
    } else if (result2 instanceof CacheGet.Miss) {
        console.log("Key 'test-key' was not found in cache 'test-cache'");
    } else if (result2 instanceof CacheGet.Error) {
        throw new Error(
            `An error occurred while attempting to get key 'test-key' from cache 'test-cache': ${result.errorCode()}: ${result.toString()}`
        );
    }

}
run();

呼び出し回数が多いため大分ばらつきが生じますが、1アイテムあたり15~30msの時間を要しています。2回API呼び出しを行うためです。
使える場面では積極的にincrementを使っていった方がよさそうです!

Discussion