2013年1月8日火曜日

VirtualBox仮想環境AndroidをEclipseからデバッグしてみた

Androidアプリ開発に本格的に着手することになるので開発環境を整えます。

AndroidアプリのIDEであるEclipseはGoogleがプラグインとSDKとエミュレータをセットにしたパッケージを配布してるのでそれを実行するだけでできてしまいます。

http://developer.android.com/sdk/index.html

Windowsはこれだけで直ぐにAndroid開発ができちゃうから便利ですね。

 

ただ、エミュレータがどうしても重たい。このバンドルされているエミュレータはARM命令をx86CPUでエミュレートすることによって動いているのですが、

命令セットのエミュレータというのはかなり高コストになります。現在のどんなにハイスペックのPCでもヌルヌル動かすのは難しいでしょう。

 

なんとかならないものかと探していたらx86で動くAndroidビルドがあるそうです。

ということはVirtual Box等の仮想化ソフトで動かせるということ。

x86なので命令セットのエミュレートも必要ありません。

そして何台でも仮想Androidを作成できます。

 

試しにやってみたところ実に簡単に動かす事ができました。

ヌルヌルとまでは行きませんが、少ないリソースでAndroidエミュレータよりかなり高速に動かすことができます。

ただ、APIレベルがあってなくてEclipseからリモートデバッグができないこともあったのでいずれやり方をまとめようと思います。

 

それにしてもEclipse + ADTは画面ゴチャゴチャで見辛い...

フルHDでも狭いから4k2kが欲しくなってきた。

2013年1月7日月曜日

Webサーバチューニング(MySQL+PHP)とりあえず版

チューニングメモ。

パラメータの細かい説明はいろんなサイトにまとめてあるので省略します。

環境としてはOSは問わずPHPでSQLゴリゴリでリクエストあたりレスポンス秒が少ないWebサービスで、

他にクローラツール等のDBサーバも請け負っています。

 

まず、見落としがちですが、

CLOSE_WAITのセッションを早く消します。

主にクローラツールが原因なのですが、TCPコネクションが無駄にkeepaliveされるので許されるギリギリの値まで削ります。

http://network.station.ez-net.jp/server/linux/network/time_wait.asp

が参考になります。

# vi /etc/sysctl.conf

に下記を追加。

net.ipv4.tcp_keepalive_time = 5

net.ipv4.tcp_keepalive_probes = 2

net.ipv4.tcp_keepalive_intvl = 2

net.ipv4.tcp_fin_timeout = 15

 

次にApacheチューニングですが、奥が深すぎるのでおおよその計算を設定して運用後、徐々に調整していきます。

私の環境では以下の様に。結構稼働範囲ギリギリです。

# vi /etc/httpd/conf/httpd.conf

Timeout 15

KeepAlive Off

HostnameLookups Off

TraceEnable Off

<IfModule prefork.c>

ServerLimit 300

StartServers      10

MinSpareServers   50

MaxSpareServers  100

MaxClients      300

MaxRequestsPerChild  4000

MaxMemFree 4096

</IfModule>

server-statusを見ながら細かい調整を重ねます。

 

そしてMySQLの設定。

どのようなリレーションでサブクエリを多用するのかしないのか。同時にいくつアクセスがあるのかなど考えて調整していきます。

私の環境では細かい接続がバンバンくるので下記の様な設定です。

# vi /etc/my.cnf

 

max_connections = 1500

 

#tuning

query_cache_limit       = 32M

query_cache_size        = 256M

 

key_buffer              = 2048M

max_allowed_packet      = 4M

thread_stack            = 192K

 

sort_buffer_size = 4M

read_buffer_size = 4M

read_rnd_buffer_size = 16M

join_buffer_size = 262144

 

wait_timeout = 120

interactive_timeout = 120

 

thread_concurrency = 300

thread_cache_size = 3000

table_cache = 10000

 

 

PHPで真っ白画面

 

また下らないことで少しハマった。

Webサーバの引越時にPHPファイルを移行してMySQLに接続するコードーがありました。

ほぼ同じ構成のサーバの引越しなので特に問題なく進むはずと思ってたのですが、php.iniの設定でエラー表示するようにしてるのに画面が真っ白です。

エラーログファイルにも何も書かれていません。

 

一時間くらいうろうろしてたところふとMySQLへ接続するDAOラッパをコピペで動かしてるのを思い出しました。

見てみると「@」アットマーク。エラー制御演算子がmysql_connectについてました。

エラーが出ないのも納得。エラー制御演算子をつけているのにも納得。

こういうことがあるからコピペする時は最大限の注意を。

 

 

2013年1月2日水曜日

何度目かのブログ開設

GAEのmiclogが死んだので今度はBloggerでブログ開設。

もう何度ブログ作りなおしたかわからないけど懲りずにやります。

IT系忘却ブログです

2011年3月25日金曜日

VBAで四捨五入、切り捨て、切り上げ

VBAでの四捨五入はRound関数、
切り捨てはRoundDown関数、
切り上げはRoundUp関数を使用します。
よく使う処理なので手軽に関数で行えるのは便利ですね。


Debug.Print "-----Round関数で四捨五入-----"
Debug.Print Round(123.4567, 1)
Debug.Print Round(123.4567, 2)
Debug.Print Round(123.4567, 3)

Debug.Print "-----RoundDown関数で切り捨て-----"
Debug.Print WorksheetFunction.RoundDown(123.4567, 1)
Debug.Print WorksheetFunction.RoundDown(123.4567, 2)
Debug.Print WorksheetFunction.RoundDown(123.4567, 3)

Debug.Print "-----RoundUp関数で切り捨て-----"
Debug.Print WorksheetFunction.RoundUp(123.4567, 1)
Debug.Print WorksheetFunction.RoundUp(123.4567, 2)
Debug.Print WorksheetFunction.RoundUp(123.4567, 3)


結果は以下のようになります

-----Round関数で四捨五入-----
123.5
123.46
123.457
-----RoundDown関数で切り捨て-----
123.4
123.45
123.456
-----RoundUp関数で切り捨て-----
123.5
123.46
123.457

2011年3月24日木曜日

VBA 高速にテキストファイル末尾を取得する

Excel、Access VBAでのファイル末尾取得する方法です
この前、InputBでのファイル読み込みが高速なことに気がついたので、
ついでにテキストファイル末尾をそこそこ高速に取得するコードを考えました。

なお、CSVファイルなんかはファイル末尾の行が改行コードのみ。
なんてことも多々ありますので、取得したファイル末尾がデータ無し、または改行コードのみなら
データのある行のデータを自動で取得する機能もつけました。
Optional引数で指定できます。

条件

・約3MBの可変長CSVファイルのファイル末尾取得。
・処理時刻の計算はVBA 超高精度タイマークラスを使っています
・時刻の単位は秒です。

ソースコード


Option Explicit

Public Function TailTextFile(ByVal File_Target As String, Optional UntilExisting As Boolean = True) As String
'===========================================================================
'ファイルの最終行を取得します
'UntilExistingがTrueなら最終行が空の場合、データが存在する行までさかのぼり、そのデータを取得します
'===========================================================================

Dim intFF As Long 'ファイル番号
Dim cnt_StrFirst As Long, cnt_StrLast As Long
Dim str_Result As String, str_Sjis As String, str_Uni As String

Dim cls_Timer As New Cl_QueryPerformance '高精度タイマークラス

Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化

intFF = FreeFile
Open File_Target For Input As #intFF
str_Sjis = InputB(FileLen(File_Target), #intFF) ' SJISのテキスト読み込み
Close #intFF

Debug.Print cls_Timer.GetQueryPerformanceTime '前回タイマー初期化時からの時間

str_Uni = StrConv(str_Sjis, vbUnicode) ' SJISからUNICODEへ

cnt_StrFirst = InStrRev(str_Uni, vbCrLf) 'テキストの最後から最初の改行コードまで
cnt_StrLast = Len(str_Uni) 'テキストすべての文字数

Debug.Print cls_Timer.GetQueryPerformanceTime '前回タイマー初期化時からの時間

If UntilExisting = False Then '最終行が空でもおかまいなし
str_Result = Mid(str_Uni, cnt_StrFirst, cnt_StrLast - cnt_StrFirst) '最終行取得
Else
Do Until cnt_StrLast &amp;lt; 1
str_Result = Mid(str_Uni, cnt_StrFirst, cnt_StrLast - cnt_StrFirst) '指定文字数区間取得
If str_Result &amp;lt;&amp;gt; &amp;quot;&amp;quot; And str_Result &amp;lt;&amp;gt; Chr(13) Then Exit Do '文字無し、改行コードのみでなかったらループ終了
cnt_StrFirst = InStrRev(str_Uni, vbCrLf, cnt_StrFirst) '次の行の開始文字数を取得
cnt_StrLast = InStr(cnt_StrFirst + 1, str_Uni, vbCrLf) '次の行の終了文字数を取得
Loop
End If

Debug.Print cls_Timer.GetQueryPerformanceTime '前回タイマー初期化時からの時間

Debug.Print str_Result

TailTextFile= str_Result

End Function


結果はこんな感じ。

0.0483  ← ファイル読み込みにかかった時間
0.0384  ← Unicodeへのコンバートにかかった時間
0.0007  ← 最終行取得抽出にかかった時間

"1999.10.26","13:18","1.05740","1.05790","1.05720","1.05770","10" ←取得したデータ

合計 87.4ミリ秒

ファイル読み込み、Unicodeコンバートに時間がかかっています。
Loop文でファイル末尾抽出をやってるのはただ高速だからです。
改行コードでSplitするほうが簡単ですが、メモリも食いますし、遅いです。

今回3MBのファイルでしたが、これが数百MBになるとこの関数は使えません。
一度メモリに全部のテキストを読み込んでることになるのでメモリが足りなくなります。

せいぜい10MBくらいのファイルに使用してやってください。

VBA テキストファイルの最も高速な読み込み方法

Excel、AccessのVBAでのファイル読み込み方法はたくさん有ります。

でも結局どのやり方が一番早いんだ!ってことでいろいろコード書いて計測してみました。

条件

・約3MBの可変長CSVファイルの全読み込みと一部のコードでは行数取得。
・処理時刻の計算はVBA 超高精度タイマークラスを使っています
・メモリ処理のRedim preserveは重たい処理ですが、可変長ファイルなのでメモリの一括確保はしませんでした。
 ファイルサイズからメモリ容量を計算してメモリを確保するともっと早くなります。メモリマッピングのような処理です。
・For文で10回同じコードを走らせてます。ですので初回以降はキャッシュが効いて高速になります。
・時刻の単位は秒です。
・最終的な文字コードはUnicodeです

・計測用コードは以下の通り
Option Explicit

Public Function ReadFileTest_LineInput(ByVal File_Target As String)
'===========================================================================
'OpenステートメントのLine Inputでの順次読み込みを行います
'===========================================================================

    Dim intFF As Long                           'ファイル番号
    Dim str_buf As String                       'ただの汎用変数
    Dim str_Strings() As String                 'ファイルの中身全部の文字列型配列
    Dim Row As Long                             '行数カウント
    Dim cls_Timer As New Cl_QueryPerformance    '高精度タイマークラス
    
    Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化
    
    intFF = FreeFile
    Open File_Target For Input As #intFF
        Do While Not EOF(intFF)           'ファイルの終端かどうかを確認します
        
            Line Input #intFF, str_buf  'データ行を読み込みます
            
            '==============================================================
            '配列化有効時
            'ReDim Preserve str_Strings(Row) As String
            'str_Strings(Row) = str_buf
            'Row = Row + 1
            '==============================================================
            
        Loop
    Close #intFF
    
    Debug.Print cls_Timer.GetQueryPerformanceTime   '前回タイマー初期化時からの時間

End Function

Public Function ReadFileTest_InputB(ByVal File_Target As String)
'===========================================================================
'OpenステートメントのInputBでの順次読み込みを行います
'===========================================================================

    Dim intFF As Long                           'ファイル番号
    Dim var_buf                                 'ただの汎用変数
    Dim str_Strings() As String                 'ファイルの中身全部の文字列型配列
    Dim Row As Long                             '行数カウント
    Dim cls_Timer As New Cl_QueryPerformance    '高精度タイマークラス
    
    Dim bytSjis As String
    Dim str_Uni As String
    
    Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化
    
    intFF = FreeFile
    Open File_Target For Input As #intFF
        bytSjis = InputB(FileLen(File_Target), #intFF)      ' SJISのテキスト読み込み
    Close #intFF
    
    str_Uni = StrConv(bytSjis, vbUnicode)    ' SJISからUNICODEへ
                                    
'    '==============================================================
'    '配列化有効時
'    var_buf = Split(str_Uni, vbCrLf) '改行コードごとに区切って配列化
'    Row = UBound(var_buf)            '行数取得
'    '==============================================================
    
    Debug.Print cls_Timer.GetQueryPerformanceTime   '前回タイマー初期化時からの時間

End Function

Public Function ReadFileTest_Open_Binary(ByVal File_Target As String)
'===========================================================================
'OpenステートメントのBinaryでの順次読み込みを行います
'===========================================================================

    Dim intFF As Long                           'ファイル番号
    Dim byt_buf() As Byte
    Dim var_buf
    Dim str_buf  As String                      'ただの汎用変数
    Dim str_Strings() As String                 'ファイルの中身全部の文字列型配列
    Dim Row As Long                             '行数カウント
    Dim cls_Timer As New Cl_QueryPerformance    '高精度タイマークラス
    Dim i As Long
    
    Dim bytSjis As String
    Dim str_Uni As String
    
    Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化
    
    intFF = FreeFile
    Open File_Target For Binary As #intFF
        ReDim byt_buf(LOF(intFF))
        Get #intFF, , byt_buf
    Close #intFF
    
    str_Uni = StrConv(byt_buf(), vbUnicode) 'Unicodeに変換
    
    '==============================================================
    '配列化有効時
    var_buf = Split(str_Uni, vbCrLf) '改行コードごとに区切って配列化
    Row = UBound(var_buf)            '行数取得
    '==============================================================
    
    Debug.Print cls_Timer.GetQueryPerformanceTime

End Function

Public Function ReadFileTest_FSO_ReadAll(ByVal File_Target As String)
'===========================================================================
'FileSystemObjectのReadAllでの一括読み込みを行います
'===========================================================================

    Dim var_buf
    Dim str_buf As String
    Dim Row As Long                             '行数カウント
    Dim cls_Timer As New Cl_QueryPerformance    '高精度タイマークラス
    Dim FSO As New FileSystemObject             'FileSystemObject
    
    Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化
    
    With FSO.OpenTextFile(File_Target, ForReading)
        str_buf = .ReadAll  '一括読み込み
        .Close
    End With
    
'    '==============================================================
'    '配列化有効時
'    var_buf = Split(str_buf, vbCrLf) '改行コードごとに区切って配列化
'    Row = UBound(var_buf)            '行数取得
'    '==============================================================
    
    Set FSO = Nothing
    Debug.Print cls_Timer.GetQueryPerformanceTime
    
End Function

Public Function ReadFileTest_FSO_ReadLine(ByVal File_Target As String)
'===========================================================================
'FileSystemObjectとTextStreamでのReadLineを行います
'===========================================================================

    Dim str_buf As String                       'ただの汎用変数
    Dim str_Strings() As String                 'ファイルの中身全部の文字列型配列
    Dim Row As Long                             '行数カウント
    Dim cls_Timer As New Cl_QueryPerformance    '高精度タイマークラス
    
    Dim FSO As New FileSystemObject
    Dim FSO_TS As TextStream            ' TextStream
    
    Call cls_Timer.GetQueryPerformanceTime 'タイマー初期化
    
    Set FSO_TS = FSO.OpenTextFile(File_Target, ForReading)
    With FSO_TS
        Do Until .AtEndOfStream
            str_buf = .ReadLine
'            '==============================================================
'            '配列化有効時
'            ReDim Preserve str_Strings(Row) As String
'            str_Strings(Row) = str_buf
'            Row = Row + 1
'            '==============================================================
        Loop
        .Close
    End With
    Set FSO_TS = Nothing
    Set FSO = Nothing
    
    Debug.Print cls_Timer.GetQueryPerformanceTime
    
End Function



・結果はこのようになりました

順次読み込み 一括読み込み 一括読み込み
Line Input
(配列化有)
Line Input
(配列化無)
InputB
(配列化有)
InputB
(配列化無)
Binary
(配列化有)
Binary
(配列化無)
1回目 0.4208 0.3645 0.1739 0.1394 0.0998 0.1167
2回目 0.2878 0.2487 0.1413 0.1072 0.0928 0.0602
3回目 0.2821 0.2459 0.1178 0.0917 0.0979 0.0549
4回目 0.2817 0.2498 0.1081 0.0909 0.0992 0.0569
5回目 0.2808 0.248 0.1083 0.0893 0.09 0.0591
6回目 0.2881 0.2452 0.1181 0.0899 0.0926 0.0568
7回目 0.283 0.2457 0.1129 0.0906 0.0922 0.0573
8回目 0.2801 0.252 0.1095 0.0908 0.0925 0.0588
9回目 0.28 0.2461 0.1085 0.0917 0.092 0.059
10回目 0.2916 0.2455 0.109 0.0917 0.0945 0.0572
平均 0.2976 0.25914 0.12074 0.09732 0.09435 0.06369
一括読み込み 順次読み込み
FileSystemObject
ReadAll
(配列化有)
FileSystemObject
ReadAll
(配列化無)
FileSystemObject
ReadLine
(配列化有)
FileSystemObject
ReadLine
(配列化無)
1回目 0.4591 0.4369 0.4437 0.4139
2回目 0.2952 0.2922 0.3263 0.2748
3回目 0.2969 0.2787 0.3184 0.274
4回目 0.2973 0.2789 0.3188 0.2757
5回目 0.3001 0.2786 0.322 0.2763
6回目 0.2964 0.292 0.319 0.2768
7回目 0.295 0.2786 0.3186 0.2743
8回目 0.2988 0.2787 0.3248 0.2739
9回目 0.2992 0.282 0.3203 0.2754
10回目 0.2942 0.2962 0.3199 0.2772
平均 0.31322 0.29928 0.33318 0.28923


結果

・OpenステートメントのBinaryモードにより一括バイナリ読み込み、Unicode変換が最も高速という結果になりました。
 まぁ当然ですね。配列化も簡単なので今後はこれをメインに使っていこう。

 おそらくこれがVBAでAPIを使わない場合でもっとも高速です。
 さらにテキストファイルの最終行の取得なんてのはさらに早くできます。
 これはログを監視するようなマクロではかなり重要です。
 まぁファイル開きっぱなしの方が高速ですが。

・数百MBものファイルなら一気に配列(メモリ)に読み込むなんてマネは恐ろしくてできません。
 FileSystemObjectとTextStreamでの順次読み込み。同時にデータに対する処理を行うっていのがいいと思います。
 これだとメモリをほとんど使わないで済みます。その変わりファイルIO中に他の作業をするので堅実なコードが必要です。

用途によって使い分けるといいものが作れそうです。