3DCGbook

映像プロダクションに所属しています。主に毎日のアウトプットを配信していこうと思います。

MayaでのgetAttr...文字列連結でのパフォーマンス

ものすごーくマニアックです。
パフォーマンスを調べるのが最近のブームなので…笑

計測お題

polygonSphereを3000作成し、
・translateX
・translateY
・translateZ
・rotateX
・rotateX
・rotateX
・scaleX
・scaleY
・scaleZ
・visibility
を取得する場合に
どの文字列連結で取得するのが一番早いのかを計測してみました。
地味でマニアックですね…笑

かつ3000では数値にそこまで差が開かなかったので、
3000*10の30000で行いました。

文字列連結パターン

連結する方法を4パターン用意しました。
1. .join
2. +演算子
3. 文字列フォーマット操作(%)
4. 文字列フォーマット操作(.format)

結果

どれも5回ずつ計測しました。

.join
0:8.858000
1:8.900000
2:8.861000
3:8.834000
4:8.907000

演算子
0:8.516000
1:8.515000
2:8.508000
3:8.508000
4:8.529000

文字列フォーマット操作(%)
0:9.142000
1:9.111000
2:9.079000
3:9.071000
4:9.082000

文字列フォーマット操作(.format)
0:10.048000
1:10.048000
2:10.013000
3:10.007000
4:10.014000

結果から見て

演算子での連結が思ってたより早かったです。
Python Speed - www.peignot.netには、

文字列連結は ''.join(seq) を使うのがベストです。

と書かれていますが二つの文字列の連結程度ではベストとは言い切れないのかもしれませんね。
個人的には文字列フォーマット操作が好きなのですが…結構差が出るもんですね。
.formatとかPythonがおすすめしている割には遅いという(^^;

今回計測に使ったコード
import time
import maya.cmds as cmds

# ノードを選択(今回は3000個のpolygonSphereを選択しました)
nodes = cmds.ls(sl=True,type="transform")

# 取得したいアトリビュート
ATTRS = ("translateX",
         "translateY",
         "translateZ",
         "rotateX",
         "rotateY",
         "rotateZ",
         "scaleX",
         "scaleY",
         "scaleZ",
         "visibility")

def oldFormatString(*args):
    startTime = time.time()
    for i in xrange(10):
        for node in nodes:
            for attr in ATTRS:
                cmds.getAttr("%s.%s" %(node,attr))
    sec = time.time() - startTime
    return sec
    
def newFormatString(*args):
    startTime = time.time()
    for i in xrange(10):
        for node in nodes:
            for attr in ATTRS:
                cmds.getAttr("{0}.{1}".format(node,attr))
    sec = time.time() - startTime
    return sec

def operatorString(*args):
    startTime = time.time()
    for i in xrange(10):
        for node in nodes:
            for attr in ATTRS:
                cmds.getAttr(node +  "." + attr)        
    sec = time.time() - startTime
    return sec

def joinString(*args):
    startTime = time.time()
    for i in xrange(10):
        for node in nodes:
            for attr in ATTRS:
                cmds.getAttr('.'.join([node,attr]))
    sec = time.time() - startTime
    return sec

def main(*args):
    calcs = {"oldFormatString" :[],
             "newFormatString" :[],
             "operatorString"  :[],
             "joinString"      :[]}
    for i in xrange(5):
        calcs["oldFormatString"].append(oldFormatString())
        calcs["newFormatString"].append(newFormatString())
        calcs["operatorString"].append(operatorString())
        calcs["joinString"].append(joinString())
    for i in calcs:
        print i
        for num,j in enumerate(calcs[i]):
            print "%i:%f" %(num,j)
        print ""
        
main()



Pythonプロフェッショナルプログラミング第2版
株式会社ビープラウド(BeProud)
秀和システム
売り上げランキング: 1,376