2

ExecutorService を使用して一連のスレッド化されたタスクを実行する EJB をサーブレットが呼び出すテスト EE7 アプリケーションがあります。同じ一連のタスクを実行しているボグ標準の Java コンソール アプリと比較すると、パフォーマンス (1 秒あたりのトランザクション数) は大きく異なります - コンソール アプリで 2.5k tps 対 EE アプリで 50 tps (どちらも、コードを 60 秒間繰り返し、EE アプリは SoapUI を介して実行されます)。

タスクは、100 ミリ秒スリープする単なるダミー実装です。テストでは、5 つの並列タスクが送信されます。タイミングは、これらすべてが予想どおり 100 ~ 101 ミリ秒で完了することを示しています。Glassfish + サーブレット + EJB は、実際にはオーバーヘッドをまったく追加していないようです。

Windows と Linux の両方で同じテストを実行しましたが、結果は同じでした。どちらの場合も、Glassfish 4.0 とデフォルトの ManagedExecutorService を使用しています。max connections/cache/bean/thread/etc の設定を 256 に増やしました。

注: EJB を呼び出すだけで、ExecutorService に何も送信しない場合、9k tps になります。タスクの待ち時間をなくすと、5,000 tps になります。私のマシンは決してリソースを使い果たしているようには見えません (CPU コアの平均は 10 ~ 25% で、システム メモリに余裕があります (jvm を調整していません))。

これは少し漠然としていますが、Glassfish の構成、または Java EE7 でのマネージド スレッドの実行に問題があると思いますか? 私は、Glassfish から少なくとも 1,000 tps を期待し、2,000 tps を期待していました。

更新: JBoss の Wildfly 8 ベータ版を試してみましたが、約 5k tps になりました。これは大きな違いです。

以下のコードから再作成するには、Netbeans 7.4 で Glassfish 4/EE7 をターゲットとする EE アプリを作成し、サーブレットと EJB を追加します。

EJB + Task クラス:

package ejb;

import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import javax.annotation.Resource;
import javax.ejb.*;
import javax.enterprise.concurrent.ManagedExecutorService;

@Stateless
@LocalBean
public class NewSessionBean {
    @Resource(name="concurrent/__defaultManagedExecutorService")
    ManagedExecutorService executor;    

    public String businessMethod() {
        long start = System.currentTimeMillis();
        String message = "<p>starting businessMethod()</p>";

        List<MyTask> tasks = new ArrayList<MyTask>();
        for(int i = 0; i < 5; i++) {
            MyTask task = new MyTask(String.format("Task %d \r\n", i));
            tasks.add(task);
        }

        List<Future<String>> futures = new ArrayList<Future<String>>();
        int taskCount = tasks.size();
        for(int i = 0; i < taskCount; i++) {
            MyTask task = tasks.get(i);
            if(task != null) {
                 futures.add(executor.submit(task));
            }
        }

        int futureCount = futures.size();
        for(int i = 0; i < futureCount; i++) {
            Future<String> future = futures.get(i);
            if(future != null) {
                try {
                    message += future.get();
                } catch (InterruptedException ex) {
                    message += ex.getMessage();
                    Logger.getLogger(NewSessionBean.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ExecutionException ex) {
                    message += ex.getMessage();
                    Logger.getLogger(NewSessionBean.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

        long end = System.currentTimeMillis();

        message += String.format("<p>took %d ms (started at %d)</p>", end-start, start);

        return message;
    }
}

class MyTask implements Callable<String> {
    String message;

    public MyTask(String message) {
        this.message = message;
    }

    @Override
    public String call() throws Exception {
        if(message == null) message = "";

        long start = System.currentTimeMillis();
        message += String.format("<p>thread %s</p>", Thread.currentThread().getName());
        message += String.format("<p>started at %d</p>", start);

        Thread.sleep(100);

        long end = System.currentTimeMillis();
        message += String.format("<p>ended at %d (duration = %d ms)</p>", end, end-start);

        return message;
    }    
}

サーブレット:

package servlet;

import java.io.*;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.*;

public class NewServlet extends HttpServlet {
    @EJB
    ejb.NewSessionBean nsb;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet NewServlet</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet NewServlet at " + request.getContextPath() + "</h1>");
            out.println(nsb.businessMethod());
            out.println("</body>");
            out.println("</html>");
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }
}
4

0 に答える 0