自作のイラレのスクリプトを大幅高速化

公開:2020/10/24
更新:2020/10/24
2 min読了の目安(約2100字TECH技術記事

はじめに

ゲムマに向けてカードゲームを作っています。カードの枚数が50枚と多いのでイラレのスクリプトを活用しています。しかし、新しいイラレになってから動作が重くなって待てなくなりました。一時停止を押すと毎回止まる場所が同じなので、重いのはここだなーと当たりをつけて高速化しました。

適当な分析

重い場所はアイテムを探す関数でした。全てのアイテムに対して名前とレイヤー名を比較しているので、50枚分のカードのアイテムから探すことになり、たしかに重そうでした。後でプロファイルの存在を知り、呼び出し回数を表示すると2万回ほど呼ばれていました。

そんなコードのビフォーアフターです。

効果は抜群だ!

体感できるレベルで爆速になりました。
めでたしめでたし。
効果はちゃんと時間の計測をするべきでしょうが、爆速です。

コードのbefore

// アイテムを名前とレイヤーで探します。
function findItemWithLayer(itemName, layerName) {
    var items = activeDocument.pageItems
    for (var n = 0; n < items.length; ++n) {
        var item = items[n]
        if (item.name == itemName && item.layer.name == layerName) {
            return item
        }
    }
    $.writeln('findItemWithLayer:not found:', layerName, ':', itemName)
    return undefined
}

コードのafter

var cache = null
function makeCacheKey(itemName, layerName) {
    var key = layerName + '/' + itemName
    return key;
}

// キャッシュを作る
function makeCache() {
    $.writeln('makeChache')
    var items = activeDocument.pageItems
    cache = {}
    for (var n = 0; n < items.length; ++n) {
        var item = items[n]
        var key = makeCacheKey(item.name, item.layer.name)
        cache[key] = item
    }
    printCache();
}

// キャッシュ内を探す
function findItemInCache(itemName, layerName) {
    if(cache==null)
    {
        return undefined;
    }
    var key = makeCacheKey(itemName, layerName)
    return cache[key]
}

// キャッシュから消す
function removeItemInCache(itemName, layerName) {
    if(cache==null)
    {
        return;
    }
    var key = makeCacheKey(itemName, layerName)
    cache[key] = undefined
}

// アイテムを名前とレイヤーで探します。
function findItemWithLayer(itemName, layerName) {

    // まずは、キャッシュに問う
    var i = findItemInCache(itemName, layerName);
    if(i!=undefined)
    {
        return i;
    }
    
    var items = activeDocument.pageItems
    for (var n = 0; n < items.length; ++n) {
        var item = items[n]
        if (item.name == itemName && item.layer.name == layerName) {
            return item
        }
    }
    $.writeln('findItemWithLayer:not found:', layerName, ':', itemName)
    return undefined
}