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付ければ安定する。するけど、直列で実行されることになるので意味ない。

*1:褒めてます

*2:ExcelのマクロからとかJScriptで書かれたWSHスクリプトからとか…

*3:synchronizedとか付けずに