読者です 読者をやめる 読者になる 読者になる

アヤチノオト

覚書のこと

里々はなんで重いのかわかったような気がしなくもなくも

注意書き

僕なりに頑張って調べたつもりですがこの記事の内容は全くもって間違っている可能性があります。
やっぱり間違ってました。新しい記事をこっちに書きました

概要

整備班でダウンロードできる里々Mc151-8のパフォーマンスを解析してみた。

解析方法

satoriteをビルドして適当なスクリプトを入力して送信する。
具体的にはこんなの。

(set、ほげ、ふが)
(loop、ほげ、10000)

結果

平均経過時間(子を含まない)が長い関数を調べました。
するとsatoritranslate.cppのSatori::Translateがぶっちぎりのトップ。
これは高速化できるのかわからない。まだソースあんまし読んでないという意味で。(別のところが問題だろうと思っていたので)

それ以外で遅い関数というとsatori_sentence.cppにあるSatori::SentenceToSakuraScriptInternalと他のいくつかの関数がおそらく同じ理由で処理に時間がかかってる。(これが本命と思ってた)
これ以下はSatori::SentenceToSakuraScriptInternalとかがなんで遅いのかについて書く。

ちなみにここから下はあんま自信ないです。

SentenceToSakuraScriptInternalがなんで遅いのか

トークをただの文字列として持っていることが原因。
里々が次に何かすべきことはあるかな?って一文字ずつ調べながら処理を分岐してるので遅い。たぶんおそらくきっと。

どうすれば一文字ずつ調べなくてよくなるか

ここでは簡単のため、里々のトークには普通の文字列と()を使った変数の展開しか無いということにする。
トークを”普通の文字列か、変数の名前のどちらかである値(直和型という)”のリストで表現する。

具体的にはこんなん。Haskellでごめん。

-- 里々の値は普通の文字列、または変数の名前ということを表すデータ型
data SaotoriValue = String String
                  | Variable String
                    deriving (Eq, Show, Read)

-- トークというのは里々の値のリストだよという宣言
type Talk = [SaotoriValue]

-- トークを文字列に変換する再帰関数
eval :: Talk -> String
-- リストが空なら空のリストを返す
eval [] = []
-- リストの先頭がただの文字列なら、中身の文字列とリストの残りをevalしたものとくっつける
eval (String x: xs) = x ++ eval xs
-- リストの先頭が変数の名前なら、変数を展開した文字列とリストの残りをevalしたものとくっつける
eval (Variable x: xs) = getValue x ++ eval xs

-- 変数名を受け取って変数の中身を返す関数
-- ここでは簡単のため引数を無視して常に"Hello world!"を返す
getValue :: String -> String
getValue _ = "Hello world!"

こんなプログラムで、「こんにちは(変数)」というトークを変換するとこうなる。

eval [String "こんにちは", Variable "変数"] -- "こんにちは Hello world!"

ほかの機能も使えるようにするには変数の定義とか選択肢を表現するデータ型とその評価関数(うえのevalってやつ)を定義していけばよい。

んでこの直和型とその評価関数みたいなパターンはBoostってライブラリのVariantを使うと出来るっぽいけどこれで速くなるかはわからない。辞書を読み込んだときに変換するコストもかかるしね。

こんだけ書いておいてあれだけどもSatori::SentenceToSakuraScriptInternalを書き換えて高速化を目論むのは現実的でない気がする。大規模工事すぎるし。
てことでSatori::Translateが高速化出来ないか調べるのがいいんでないかな。
(もう疲れたのでなげやり