カレントディレクトリに入ってるExcelブックを1つずつ処理する
カレントディレクトリに入ってるExcelブックを1つずつ開いて、特定のシートを選択して、特定の列をパーズして、○×の件数を求めるスクリプト書いた。
var excel = WScript.CreateObject("Excel.Application"); excel.Visible = true; excel.DisplayAlerts = false; var shell = WScript.CreateObject("WScript.Shell"); var fs = WScript.CreateObject("Scripting.FileSystemObject"); var folder = fs.GetFolder(shell.CurrentDirectory); var files = new Enumerator(folder.Files); WScript.Echo("シート名\tOK件数\tNG件数"); for(files.moveFirst(); !files.atEnd(); files.moveNext()){ if(files.item().Name.search(/.+\.xls$/) >= 0){ var file = files.item().Name; var fullPath = folder + "\\" + file; var book = excel.Workbooks.Open(fullPath); var sheet = book.Worksheets("Sheet1"); var last = sheet.UsedRange.Rows.Count; sheet.Range("A1:AZ65536").UnMerge(); var OK = 0; var NG = 0; for(i = 1; i <= last; i += 1){ if(sheet.Cells(i, 27).Value != null){ if(sheet.Cells(i, 27).Value.indexOf("○") == 0){ OK += 1; } if(sheet.Cells(i, 27).Value.indexOf("×") == 0){ NG += 1; } } } WScript.Echo(file + "\t" + OK + "\t" + NG); book.Close(); } } excel.Quit();
こんな感じで使う。
>cscript //nologo excel.js シート名 OK件数 NG件数 Book1.xls 13 20 Book2.xls 10 7
BCL easyPDF SDKていうののベンチマーク取ってみた(続き)
昨日やってみたベンチマークは、ふつうのアプリだったけど、Webアプリでも同じ性能がでるかやってみた。
ベンチマークのルール
jpeg画像をサーバー側にあらかじめ連番で1万件作っておく。名前は0000.jpg〜9999.jpgとする。クライアントから順次変換リクエストを投げて、0000.jpg〜9999.jpgをそれぞれPDFに変換する。名前は0000.pdf〜9999.pdfとする。このPDF変換にかかった時間を計測する。サーブレットコンテナはApache Tomcat 6.0.35 Serverとする。
サーバー側のプログラム
サーバー側のプログラムはこんな感じになった。Tomcatだと自動的にスレッドで処理してくれるので、スレッド処理を自前で実装してた部分を省いた。
import com.bcl.easypdf.*; import com.bcl.easypdf.EasyPDFPrinter.*; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class PDFprint extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileNo = request.getParameter("fileNo"); String inputFileName = ""; inputFileName = String.format("C:\\Users\\hide\\Documents\\%s.jpg", fileNo); System.out.println(inputFileName); String outputFileName = ""; outputFileName = String.format("C:\\Users\\hide\\Documents\\%s.pdf", fileNo); System.out.println(outputFileName); EasyPDF.initialize(); IPrinter printer = new IPrinter(); IPrintJob pj = printer.getPrintJob(); pj.PrintOut(inputFileName, outputFileName); EasyPDF.uninitialize(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>\n"); out.println("<head><title>Servlet Sample</title></head>"); out.println("<body>"); out.println(inputFileName); out.println(outputFileName); out.println("</body>"); out.println("</html>"); out.close(); } }
クライアント側のプログラム
クライアント側のプログラムは、なるべく早くリクエストを投げるために、スレッドで実行してた部分を流用して、リクエストを投げるようにした。
import java.io.*; import java.net.*; class PrintRequest { public static void main(String[] args) { long timeMillisStart = System.currentTimeMillis(); // スレッドを32個作成する MyThread[] threads = new MyThread[32]; for (int i = 0; i < 32; i++) { threads[i] = new MyThread(i); threads[i].start(); } // スレッドがすべて終了するのを待つ for (int i = 0; i < 32; i++) { try { threads[i].join(); } catch (InterruptedException e) { System.out.println(e); } } long timeMillisEnd = System.currentTimeMillis(); long time = timeMillisEnd - timeMillisStart; System.out.println(time + "ms. " + time/1000 + "s" ); } } // スレッド class MyThread extends Thread { int threadNo; MyThread(int i){ threadNo = i; } public void run(){ for(int i = 0; i < 10000; i++){ if(i % 32 == threadNo){ String requestUrl = ""; requestUrl = String.format("http://localhost:8080/PDFprint?fileNo=%04d", i); System.out.println(requestUrl); try { URL accessURL = new URL(requestUrl); HttpURLConnection con = (HttpURLConnection)accessURL.openConnection(); con.setRequestMethod("GET"); con.connect(); BufferedInputStream bis = new BufferedInputStream(con.getInputStream()); int data; while ( (data = bis.read()) != -1 ) System.out.write(data); } catch (java.net.MalformedURLException e){ e.printStackTrace(); } catch (java.io.IOException e){ e.printStackTrace(); } } } } }
結果
C:\Users\hide\Documents>java PrintRequest 〜途中省略〜 http://localhost:8080/PDFprint?fileNo=9990 <html> <head><title>Servlet Sample</title></head> <body> C:\Users\hide\Documents\9972.jpg C:\Users\hide\Documents\9972.pdf </body> </html> <html> <head><title>Servlet Sample</title></head> <body> C:\Users\hide\Documents\9990.jpg C:\Users\hide\Documents\9990.pdf </body> </html> 211650ms. 211s
211秒かかった。だいたい4分足らず。念のため全件できてるか確認してみる。
C:\Users\hide\Documents>dir *.pdf 〜途中省略〜 2012/05/06 15:34 394,675 9990.pdf 2012/05/06 15:34 394,675 9991.pdf 2012/05/06 15:34 394,675 9992.pdf 2012/05/06 15:34 394,675 9993.pdf 2012/05/06 15:34 394,675 9994.pdf 2012/05/06 15:34 394,675 9995.pdf 2012/05/06 15:34 394,675 9996.pdf 2012/05/06 15:34 394,675 9997.pdf 2012/05/06 15:34 394,675 9998.pdf 2012/05/06 15:34 394,675 9999.pdf 10000 個のファイル 3,946,750,000 バイト 0 個のディレクトリ 60,136,988,672 バイトの空き領域
できてるっぽい。この処理してる間、タスクマネージャーでCPU使用率見てみた。4コア全てで100%に張り付く感じで推移してた。そのほとんどをTomcatのプロセスが占めてて、easyPDFのプロセスは1%程度だった。
BCL easyPDF SDKていうののベンチマーク取ってみた
画像をPDFに変換するのっていろいろなやり方があると思うけど、easyPDFていうソフトもそういう機能がある。で、easyPDFはWindowsのCOMとして動作するかなり変態的*1なソフト。COMとして呼び出せるってことはどっからでも呼び出せる*2ってことで、夢が広がるじゃないですかー。どのくらい性能でるのかベンチマーク取ってみた。
ベンチマークのルール
jpeg画像をあらかじめ連番で1万件作っておく。名前は0000.jpg〜9999.jpgとする。0000.jpg〜9999.jpgをそれぞれPDFに変換する。名前は0000.pdf〜9999.pdfとする。このPDF変換にかかった時間を計測する。マシンのスペックはこんな感じ。
OS: Windows 7 , 64 bit Build 7601 Service Pack 1 CPU:total 4 (2 cores per cpu, 2 threads per core) family 6 model 37 stepping 2, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, ht ※Intel(R) Core(TM) i3 CPU 540 @ 3.07GHz Memory: 4k page, physical 3923448k(1523204k free), swap 7845044k(4954616k free) vm_info: Java HotSpot(TM) 64-Bit Server VM (20.7-b02) for windows-amd64 JRE (1.6.0_32-b05), built on Apr 5 2012 13:39:03 by "java_re" with MS VC++ 8.0 (VS2005)
プログラム
こんな感じのプログラムを作って実行してみた。Javaのスレッドを利用してる。32スレッドを非同期で*3実行して、1万件のファイルを32スレッドで分担して処理する。
import com.bcl.easypdf.*; import com.bcl.easypdf.EasyPDFPrinter.*; import java.io.File; class PrintPDF { public static void main(String[] args) { long timeMillisStart = System.currentTimeMillis(); // スレッドを32個作成する MyThread[] threads = new MyThread[32]; for (int i = 0; i < 32; i++) { threads[i] = new MyThread(i); threads[i].start(); } // スレッドがすべて終了するのを待つ for (int i = 0; i < 32; i++) { try { threads[i].join(); } catch (InterruptedException e) { System.out.println(e); } } long timeMillisEnd = System.currentTimeMillis(); long time = timeMillisEnd - timeMillisStart; System.out.println(time + "ms. " + time/1000 + "s" ); } } // スレッド class MyThread extends Thread { int threadNo; MyThread(int i){ threadNo = i; } public void run(){ for(int i = 0; i < 10000; i++){ if(i % 32 == threadNo){ String input = String.format("%04d.jpg", i); File inputFile = new File(input); String inputFileName = ""; try { inputFileName = inputFile.getCanonicalPath(); } catch (java.io.IOException e){ e.printStackTrace(); } System.out.println(inputFileName); String output = String.format("%04d.pdf", i); File outputFile = new File(output); String outputFileName = ""; try { outputFileName = outputFile.getCanonicalPath(); } catch (java.io.IOException e){ e.printStackTrace(); } System.out.println(outputFileName); EasyPDF.initialize(); IPrinter printer = new IPrinter(); IPrintJob pj = printer.getPrintJob(); pj.PrintOut(inputFileName, outputFileName); EasyPDF.uninitialize(); } } } }
結果
C:\Users\hide\Documents>java PrintPDF
〜途中省略〜
C:\Users\hide\Documents\9868.jpg
C:\Users\hide\Documents\9868.pdf
C:\Users\hide\Documents\9900.jpg
C:\Users\hide\Documents\9900.pdf
C:\Users\hide\Documents\9932.jpg
C:\Users\hide\Documents\9932.pdf
C:\Users\hide\Documents\9964.jpg
C:\Users\hide\Documents\9964.pdf
C:\Users\hide\Documents\9996.jpg
C:\Users\hide\Documents\9996.pdf
253235ms. 253s
253秒かかった。だいたい4分ちょい。非同期で実行してるので、最後が9999になるとは限らないってことっすね。念のため全件できてるか確認してみる。
C:\Users\hide\Documents>dir *.pdf 〜途中省略〜 2012/05/05 00:54 394,675 9990.pdf 2012/05/05 00:54 394,675 9991.pdf 2012/05/05 00:54 394,675 9992.pdf 2012/05/05 00:54 394,675 9993.pdf 2012/05/05 00:54 394,675 9994.pdf 2012/05/05 00:54 394,675 9995.pdf 2012/05/05 00:54 394,675 9996.pdf 2012/05/05 00:54 394,675 9997.pdf 2012/05/05 00:54 394,675 9998.pdf 2012/05/05 00:54 394,675 9999.pdf 10000 個のファイル 3,946,750,000 バイト 0 個のディレクトリ 60,342,808,576 バイトの空き領域
できてるっぽい。この処理してる間、タスクマネージャーでCPU使用率見てみた。4コア全てで100%に張り付く感じで推移してた。そのほとんどをJavaのプロセスが占めてて、easyPDFのプロセスは1%程度だった。
スレッド数について
スレッド数をなんで32個にしたかというと、あんまり増やすとException吐いて変換できないことがあるから。だいたい47個を超えるとException吐く感じ。たぶん47個くらいまでならいけるんじゃないかなー、と思う。4コアなので4の倍数ということで32個にしてみた。ちなみに1000スレッドとかにするとクラッシュダンプ吐いてJVMが死ぬ。あ、1000スレッドとかにしても、synchronized付ければ安定する。するけど、直列で実行されることになるので意味ない。
DOMを操作して特定のデータを抽出するスクリプト書いた
Apacheってmod_proxy_balancerていうモジュールを使うとリバースプロキシとして使えて、ブラウザからbalancer-managerていう管理画面にアクセスすると、振り分けっぷりが分かる。だけどいちいちブラウザでぽちぽちリロードすんのめんどくさいので、自動的にログ取るスクリプト書いた。
このページの赤枠のとこだけ引っこ抜きたい。
こんな感じになった。
var uri = WScript.Arguments(0); var ie = WScript.CreateObject("InternetExplorer.Application"); ie.Visible = true; while(ie != null){ startTime = +new Date(); ie.Navigate(uri); while(ie.Busy || ie.readystate != 4){ WScript.Sleep(100); } var h3s = ie.document.getElementsByTagName("h3"); var tables = ie.document.getElementsByTagName("table"); for(var i = 0; i < h3s.length; i++){ WScript.Echo(h3s[i].innerText); for(var j = 1; j < tables[i * 2 + 1].rows.length; j++){ WScript.Echo(tables[i * 2 + 1].rows[j].cells[0].getElementsByTagName("a")[0].innerHTML + "\t" + tables[i * 2 + 1].rows[j].cells[5].innerHTML + "\t" + tables[i * 2 + 1].rows[j].cells[6].innerHTML); } } endTime = +new Date(); WScript.Echo(new Date() + "\t" + (endTime - startTime) + "\n"); WScript.Sleep(60000); }
こんな感じで使う。
>cscript //nologo bmstat.js http://192.168.2.31/balancer-manager LoadBalancer Status for balancer://backend http://192.168.2.32/ Ok 11 http://192.168.2.33/ Ok 10 Mon Jan 9 17:59:47 UTC+0900 2012 118 LoadBalancer Status for balancer://backend http://192.168.2.32/ Ok 11 http://192.168.2.33/ Ok 10 Mon Jan 9 17:59:52 UTC+0900 2012 121
去年の9/27に作ったスクリプト↓を改造したもの。
HT-03AでイオンのSIMを使う
コムギさんとこのとおりやったらイオンのSIMが使えたので忘れないうちにやったことをメモ。
3. パソコンがスマホを認識できたか確認する。
>adb devices
List of devices attached
HT96KLF01634 device
“device”ていうのが表示されたら大丈夫っぽい。(引っこ抜いてから同じコマンド打つと表示されなくなる)adbコマンドの準備については2011-10-25の日記参照。
4. ライブラリをスマホへ転送する。
コムギさんところで紹介されているライブラリを取ってきておいて、adb pushでとりあえずSDカードにコピーする。
イイ:モバイル
>adb push libhtc_ril.so /sdcard/libhtc_ril.so 1028 KB/s (445368 bytes in 0.423s)
6. ライブラリを新しいやつで上書きする。
mvしてみる。
# mv /sdcard/libhtc_ril.so /system/lib/libhtc_ril.so mv /sdcard/libhtc_ril.so /system/lib/libhtc_ril.so failed on '/sdcard/libhtc_ril.so' - Cross-device link
Cross-device linkとかいうのでfaildしちゃった。
ddでやってみる。
# dd if=/sdcard/libhtc_ril.so of=/system/lib/libhtc_ril.so dd if=/sdcard/libhtc_ril.so of=/system/lib/libhtc_ril.so /system/lib/libhtc_ril.so: cannot open for write: Read-only file system
fsがRead-onlyだった…
mount状況を確認してみる。
# mount mount rootfs / rootfs ro 0 0 tmpfs /dev tmpfs rw,mode=755 0 0 devpts /dev/pts devpts rw,mode=600 0 0 proc /proc proc rw 0 0 sysfs /sys sysfs rw 0 0 tmpfs /sqlite_stmt_journals tmpfs rw,size=4096k 0 0 none /dev/cpuctl cgroup rw,cpu 0 0 /dev/block/mtdblock3 /system yaffs2 ro 0 0 /dev/block/mtdblock5 /data yaffs2 rw,nosuid,nodev 0 0 /dev/block/mtdblock4 /cache yaffs2 rw,nosuid,nodev 0 0 /dev/block//vold/179:1 /sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,code page=cp437,iocharset=iso8859-1,shortname=mixed,utf8 0 0
/systemはRead-onlyすね。remountしてリトライしてみる。
# mount -o rw,remount /dev/block/mtdblock3 /system mount -o rw,remount /dev/block/mtdblock3 /system # dd if=/sdcard/libhtc_ril.so of=/system/lib/libhtc_ril.so dd if=/sdcard/libhtc_ril.so of=/system/lib/libhtc_ril.so 869+1 records in 869+1 records out 445368 bytes transferred in 0.379 secs (1175113 bytes/sec) # exit exit $ exit exit
よっしゃ。無理矢理感はあるけど上書きできた。
7. APNの設定をする。
スマホを再起動してから、APNの設定をしてみた。
編集したのは以下の4項目だけ。これでつながった。
名前 | bmobile |
APN | dm.jplat.net |
ユーザー名 | bmobile@aeon |
パスワード | bmobile |
セグメンテーションフォールトを発生させてみる
セグメンテーションフォールトを発生させるプログラム書いてみた。
int main () { int* x = 10; printf ("%d\n", *x); }
コンパイルして実行してみる。
>gcc segfault.c -o segfault.exe segfault.c: 関数 'main' 内: segfault.c:3:12: 警告: 初期化で整数からキャスト無しにポインタを作成しています [デフォルトで有効] segfault.c:4:3: 警告: 組み込み関数 'printf' の互換性がない暗黙的な宣言です [デフォルトで有効] >segfault
こんなダイアログ出た。
終了するしかなくなった。
xはint*というふうに宣言してるので、ふつうの変数じゃなくてポインタになる。で、*xで表されるアドレス(10番地)をプリントしようとして、セグメンテーションフォールトが発生する。アドレス10番地はユーザープログラムだと読み取ることすらできないみたい。(Windows 7で検証)
UNIXライクのオペレーティングシステム上では、不正なメモリにアクセスをするプロセスはSIGSEGVシグナルを受け取る。Microsoft Windows上では、不正なメモリにアクセスするプロセスはSTATUS_ACCESS_VIOLATION例外を受け取る。
wikipedia:セグメンテーション違反
LANケーブルが差さってないときにIPアドレスを確認する
ipconfigコマンドってアクティブなインターフェースしか出てこない感じだけど、オフラインのときにも確認できるコマンドないかなー、と思って探してみた。
こんな感じだった。
Windowsキー+R
ファイル名を指定して実行が開くので、
cmd.exe /k netsh interface ipv4 show address
て打つとこんな感じで出る。
>cmd.exe /k netsh interface ipv4 show address インターフェイスの構成 "ネットワーク ブリッジ" DHCP 有効: はい IP アドレス: 192.168.2.25 サブネット プレフィックス: 192.168.2.0/24 (マスク 255.255.255.0) デフォルト ゲートウェイ: 192.168.2.1 ゲートウェイ メトリック: 0 インターフェイス メトリック: 10 インターフェイスの構成 "Loopback Pseudo-Interface 1" DHCP 有効: いいえ IP アドレス: 127.0.0.1 サブネット プレフィックス: 127.0.0.0/8 (マスク 255.0.0.0) インターフェイス メトリック: 50
ブリッジ組んでるとそれぞれのインターフェース名(ローカル エリア接続とか)は出てこないんすね。
省略形はこんな感じ。
cmd /k netsh i i sh a