下の調査結果を元に、htmlの生成部分のリファクタリングをしてました。
・無理に''.joinは使わない。
・速度を理由に文字を定数化しない。
明日は、ログインフォームを作ろう。
トレーディングカードゲーム「Magic:The Gathering」の攻略サイト MTG-Guild の 開発日誌です。 Google App Engine - Python で構築スタート! ・・・どうなることやら
2010年11月4日木曜日
Pythonの文字列結合のパフォーマンス
Python2.5.4で、文字列結合の速度についていろいろ試してみました。
あらかじめb='b'、c='c'となっている場合:
a='b'+'c'
a=b+c
これはどちらも、ほぼ同じ時間でした。
変数に入れているほうが、オブジェクトの生成がなくて速そうですが、意外にもそうではありませんでした。
a=''.join(['b','c'])
a=''.join(('b','c'))
当然、下が速いです。リスト内包表記を使わないなら、タプルを使ったほうが良いですね。
あらかじめ_join=''.joinとなっている場合:
a=''.join(('b','c'))
a=_join(('b','c'))
これも、下が速いです。3回以上''.join(iter)を使うようでしたら、変数に入れておいたほうが速かったです。
あらかじめ_join=''.joinとなっている場合:
a='b'+'c'
a=_join(('b','c'))
これは、上のほうが速かったです。文字列が長かったり、何度も結合する場合は、_join(iter)のほうが速いはずなのですが、それは調査中です。
あらかじめb='b'、c='c'となっている場合:
a='b'+'c'
a=b+c
これはどちらも、ほぼ同じ時間でした。
変数に入れているほうが、オブジェクトの生成がなくて速そうですが、意外にもそうではありませんでした。
a=''.join(['b','c'])
a=''.join(('b','c'))
当然、下が速いです。リスト内包表記を使わないなら、タプルを使ったほうが良いですね。
あらかじめ_join=''.joinとなっている場合:
a=''.join(('b','c'))
a=_join(('b','c'))
これも、下が速いです。3回以上''.join(iter)を使うようでしたら、変数に入れておいたほうが速かったです。
あらかじめ_join=''.joinとなっている場合:
a='b'+'c'
a=_join(('b','c'))
これは、上のほうが速かったです。文字列が長かったり、何度も結合する場合は、_join(iter)のほうが速いはずなのですが、それは調査中です。
2010年11月3日水曜日
開発進捗
''.join(list)のlistは、イテレート可能であればlistで無くても良いみたい。
listに間違ってジェネレータをそのまま指定したら、そのまま動いたので気がつきました。
試行錯誤した結果、''.join(ジェネレータ)で、単純な文字結合の約1.3倍の速度になりました。(ローカル環境での実測。本番環境ではどうなのかは未検証)
unittestのテストケースのメソッドにコメントを入れたら、noseの出力結果にコメントが出力された。
そんな小便利な機能があるのですね。
ただ、通常は「メソッド名(テストケースのクラス名)」と表示されたところが、「コメント」と出力されるので、どこの結果なのかがわかりにくいと思いました。
半端にコメントいれると、かえってまずそうなので、今はコメントを入れない方向です。
listに間違ってジェネレータをそのまま指定したら、そのまま動いたので気がつきました。
試行錯誤した結果、''.join(ジェネレータ)で、単純な文字結合の約1.3倍の速度になりました。(ローカル環境での実測。本番環境ではどうなのかは未検証)
unittestのテストケースのメソッドにコメントを入れたら、noseの出力結果にコメントが出力された。
そんな小便利な機能があるのですね。
ただ、通常は「メソッド名(テストケースのクラス名)」と表示されたところが、「コメント」と出力されるので、どこの結果なのかがわかりにくいと思いました。
半端にコメントいれると、かえってまずそうなので、今はコメントを入れない方向です。
2010年11月2日火曜日
開発進捗とか
今何している?:
・Htmlを生成する俺ライブラリを作成中:
・最近気がついてションボリ:
・標準ライブラリのxml.etree.ElementTreeと中身がほとんど被っていた!
・でも俺ライブラリのほうが表記が短くて済むのでよしとする。
・それにちらっと覗いた感じでは標準ライブラリも大した事をやっていない。
・xml文字列作成部分では、高速化する余地がありそう。
今後何をしたい?
・Htmlを生成する俺ライブラリの改善:
・サービスを広げようと思うと、やっぱり速くしたい。
・文字列の結合は、やっぱり''.join(list)が速いみたい。
・イッシー環境では、listをリスト内包表記にすると、小さな文字列でもだいぶ違った。
・listを育ててから''.join(list)すると、あんまり差が出ないことも多い。
・html文字列生成時は、今は文字列連結でやっているので、高速化の余地がある。
・リストを育てていくと、リストの再生成で時間がかかるはずなので、
全体をなめるイテレーター処理を定義して、それをリスト内包表記にして、join(list)とさせよう。
・html文字列生成時の文字コードの指定は、内部的にはグローバル変数を介してやろう。
そのほうが引数のやり取りが減って速そう。
・エスケープ処理がないので改善が必要
・Formのhtmlは作成できるけど、それだけ。
・ブラウザから返ってきたrequestデータをパースしてFormで受け取る処理が欲しい
・スタイルクラスをうまく定義できるようにしたい
・responseのヘッダーに文字コードを設定する処理をうまくやりたい
・ログインフォームの作成:
・具体的に使ってみないと、ライブラリの使い勝手がわからない
・テーブル操作もやりたい
・そろそろセッション維持についても実装しながら考えたい
ここ数ヶ月を振りかえって思ったこと:
・テスト駆動開発はすばらしい。リファクタリングが思う存分出来る。
・不必要に下調べはしないほうが良い。調べたことを忘れてしまう。
すぐに実装しようと思っていることに対してのみ調べるべき。
・フレームワークは、一度自作すると良い。
ほとんどが既存の仕組みで代用できますが、勉強になる。
そうして初めて、既存のフレームワークのありがたさが良くわかる。
・Htmlを生成する俺ライブラリを作成中:
・最近気がついてションボリ:
・標準ライブラリのxml.etree.ElementTreeと中身がほとんど被っていた!
・でも俺ライブラリのほうが表記が短くて済むのでよしとする。
・それにちらっと覗いた感じでは標準ライブラリも大した事をやっていない。
・xml文字列作成部分では、高速化する余地がありそう。
今後何をしたい?
・Htmlを生成する俺ライブラリの改善:
・サービスを広げようと思うと、やっぱり速くしたい。
・文字列の結合は、やっぱり''.join(list)が速いみたい。
・イッシー環境では、listをリスト内包表記にすると、小さな文字列でもだいぶ違った。
・listを育ててから''.join(list)すると、あんまり差が出ないことも多い。
・html文字列生成時は、今は文字列連結でやっているので、高速化の余地がある。
・リストを育てていくと、リストの再生成で時間がかかるはずなので、
全体をなめるイテレーター処理を定義して、それをリスト内包表記にして、join(list)とさせよう。
・html文字列生成時の文字コードの指定は、内部的にはグローバル変数を介してやろう。
そのほうが引数のやり取りが減って速そう。
・エスケープ処理がないので改善が必要
・Formのhtmlは作成できるけど、それだけ。
・ブラウザから返ってきたrequestデータをパースしてFormで受け取る処理が欲しい
・スタイルクラスをうまく定義できるようにしたい
・responseのヘッダーに文字コードを設定する処理をうまくやりたい
・ログインフォームの作成:
・具体的に使ってみないと、ライブラリの使い勝手がわからない
・テーブル操作もやりたい
・そろそろセッション維持についても実装しながら考えたい
ここ数ヶ月を振りかえって思ったこと:
・テスト駆動開発はすばらしい。リファクタリングが思う存分出来る。
・不必要に下調べはしないほうが良い。調べたことを忘れてしまう。
すぐに実装しようと思っていることに対してのみ調べるべき。
・フレームワークは、一度自作すると良い。
ほとんどが既存の仕組みで代用できますが、勉強になる。
そうして初めて、既存のフレームワークのありがたさが良くわかる。
2010年11月1日月曜日
WindowsXP(eclipse)でGAE/Pのテスト駆動開発(nose)
WindowsXP環境でeclipse(PyDev)を使ってGoogle App Engine の開発をしているのですが、
・テストコードを簡単に実行したい
・エラーの有無を実行結果の色で判別したい
という思いから、以下のようなバッチを作ってみました。
<nosetest.bat>
@ECHO OFF
CD /D %~dp0
REM ========================================
REM nosetests 起動バッチ
REM ①nosetests にパラメータを指定して起動、出力結果を一時ファイルに保存
REM ②テストでエラーなし:テスト結果を標準出力に出力
REM テストでエラーあり:テスト結果をエラー出力に出力
REM ③30秒間(パラメータ1で変更可能)そのままポーズして終了
REM ========================================
REM 起動パラメータ:
REM パラメータ1=指定された秒数だけ表示(デフォルトは30秒)
REM パラメータ2=nosetestsの追加パラメータ
REM ========================================
IF "%1"=="" (SET WAIT_TIME=30) ELSE (SET WAIT_TIME=%1)
SET EXTENDS = %~2
SET /A WAIT_TIME=%WAIT_TIME%+1 >NUL
REM ======================================
REM 内部パラメータ:
REM EXE_COMAND=nosetest.exeの起動コマンド(必要に応じてpathも指定)
REM SRC_PATH=ソースディレクトリの相対パス
REM NOSETESTS_RESULT_FILE=noseの実行結果の保存ファイル
REM ======================================
SET EXE_COMAND=nosetests.exe -v --with-gae --gae-lib-root="C:\Program Files\Google\google_appengine" --without-sandbox
SET SRC_PATH=..\src
SET NOSETESTS_RESULT_FILE=nosetests_result.txt
REM ======================================
REM 実処理
REM ======================================
SET EXE_COMAND=%EXE_COMAND% %EXTENDS%
TITLE %EXE_COMAND%
CD /D %SRC_PATH%
%EXE_COMAND% 2>%~dp0\%NOSETESTS_RESULT_FILE%
CD /D %~dp0
FINDSTR "FAILED (*" %NOSETESTS_RESULT_FILE% > NUL
SET ERROR_CODE=%ERRORLEVEL%
IF "%ERROR_CODE%"=="0" (color 4F & type %NOSETESTS_RESULT_FILE% 1>&2 & SET RETURN_CODE=1) ELSE (color 27 & type %NOSETESTS_RESULT_FILE% 2>&1 & SET RETURN_CODE=0)
@PING -n %WAIT_TIME% localhost >NUL
EXIT /B %ERROR_CODE%
動作確認環境:WindowsXP SP3 + eclipse3.5.2 ( +PyDev 1.6.3 + Nose 0.11.4+ NoseGAE 0.1.7)
配置はこんな感じを前提にしてます。
[workspace]\[project]\bat\nosetest.bat
[workspace]\[project]\src\app.yaml
[workspace]\[project]\src\app.yaml
[workspace]\[project]\src\main.py
[workspace]\[project]\src\test_main.py
[workspace]\[project]\src\htmlgenerator\base.py
[workspace]\[project]\src\htmlgenerator\test_base.py
使い方:
その1: 外部ツールにnosetests.batを登録、起動時のパラメータに0を指定。
登録した外部ツールを、一度実行。
「前回実行した外部ツールを起動」のメニューに、Ctrl+Tを割り当て。
その2:
ショートカットを作成して、スタートメニューに登録。
Windowsキーを押してスタートメニューを表示させて、Nを押す。
・テストコードを簡単に実行したい
・エラーの有無を実行結果の色で判別したい
という思いから、以下のようなバッチを作ってみました。
<nosetest.bat>
@ECHO OFF
CD /D %~dp0
REM ========================================
REM nosetests 起動バッチ
REM ①nosetests にパラメータを指定して起動、出力結果を一時ファイルに保存
REM ②テストでエラーなし:テスト結果を標準出力に出力
REM テストでエラーあり:テスト結果をエラー出力に出力
REM ③30秒間(パラメータ1で変更可能)そのままポーズして終了
REM ========================================
REM 起動パラメータ:
REM パラメータ1=指定された秒数だけ表示(デフォルトは30秒)
REM パラメータ2=nosetestsの追加パラメータ
REM ========================================
IF "%1"=="" (SET WAIT_TIME=30) ELSE (SET WAIT_TIME=%1)
SET EXTENDS = %~2
SET /A WAIT_TIME=%WAIT_TIME%+1 >NUL
REM ======================================
REM 内部パラメータ:
REM EXE_COMAND=nosetest.exeの起動コマンド(必要に応じてpathも指定)
REM SRC_PATH=ソースディレクトリの相対パス
REM NOSETESTS_RESULT_FILE=noseの実行結果の保存ファイル
REM ======================================
SET EXE_COMAND=nosetests.exe -v --with-gae --gae-lib-root="C:\Program Files\Google\google_appengine" --without-sandbox
SET SRC_PATH=..\src
SET NOSETESTS_RESULT_FILE=nosetests_result.txt
REM ======================================
REM 実処理
REM ======================================
SET EXE_COMAND=%EXE_COMAND% %EXTENDS%
TITLE %EXE_COMAND%
CD /D %SRC_PATH%
%EXE_COMAND% 2>%~dp0\%NOSETESTS_RESULT_FILE%
CD /D %~dp0
FINDSTR "FAILED (*" %NOSETESTS_RESULT_FILE% > NUL
SET ERROR_CODE=%ERRORLEVEL%
IF "%ERROR_CODE%"=="0" (color 4F & type %NOSETESTS_RESULT_FILE% 1>&2 & SET RETURN_CODE=1) ELSE (color 27 & type %NOSETESTS_RESULT_FILE% 2>&1 & SET RETURN_CODE=0)
@PING -n %WAIT_TIME% localhost >NUL
EXIT /B %ERROR_CODE%
動作確認環境:WindowsXP SP3 + eclipse3.5.2 ( +PyDev 1.6.3 + Nose 0.11.4+ NoseGAE 0.1.7)
配置はこんな感じを前提にしてます。
[workspace]\[project]\bat\nosetest.bat
[workspace]\[project]\src\app.yaml
[workspace]\[project]\src\app.yaml
[workspace]\[project]\src\main.py
[workspace]\[project]\src\test_main.py
[workspace]\[project]\src\htmlgenerator\base.py
[workspace]\[project]\src\htmlgenerator\test_base.py
使い方:
その1: 外部ツールにnosetests.batを登録、起動時のパラメータに0を指定。
登録した外部ツールを、一度実行。
「前回実行した外部ツールを起動」のメニューに、Ctrl+Tを割り当て。
その2:
ショートカットを作成して、スタートメニューに登録。
Windowsキーを押してスタートメニューを表示させて、Nを押す。
登録:
投稿 (Atom)