Phát triển Java 2.0: Theo dõi ứng dụng Java với Health Center API, Phần 2

Thêm một khung nhìn method-profiling vào ứng dụng phát hiện tắc nghẽn (deadlock)

Bản phát hành 2.1 của Health Center chứa các tính năng mạnh mẽ cho lập trình giao diện ứng dụng. Thư viện API cho phép những nhà lập trình Java nhúng Health Center trong các ứng dụng của họ và khai thác sức mạnh giám sát theo dõi của nó để khắc phục các vấn đề. Trong phần 2 này, chúng ta sẽ phát triển ứng dụng ở Phần 1 và thêm vào một khung nhìn method-profiling để biết nơi mà ứng dụng chiếm dụng nhiều chu kỳ hoạt động của CPU.

Toby Corbin, Kỹ sư phần mềm, IBM Japan

Ảnh của Toby CorbinToby Corbin là trưởng nhóm phát triển cho công cụ theo dõi Health Center; ông cũng phát triển các công cụ khác bên trong Trung tâm công nghệ Java của IBM. Ông bắt đầu làm việc ở IBM từ năm 2001, trong vòng bốn năm, ông đã phát triển môi trường runtime Java hỗ trợ ngôn ngữ và toàn cầu hóa. Toby đã phát triển các thư viện Swing và AWT trong hai năm.



22 08 2013

Công cụ giám sát và chuẩn đoán của IBM (IBM® Monitoring and Diagnostics tools) cho Java - Health Center là một công cụ chuẩn đoán miễn phí, chi phí thấp và API cho việc giám sát một ứng dụng chạy trên máy ảo Java của IBM (IBM Java virtual machine - JVM). Điều đặc biệt mà API này có thể làm đã được nhắc đến trong Phần 1. Trong bài này, ta sẽ sử dụng ứng dụng phát hiện tắc nghẽn đã phát triển ở Phần 1 và thêm vào một khung nhìn method-profiling để hiển thị nơi mà ứng dụng của bạn chiếm dụng chu kỳ CPU. (Xem mục Tải về để lấy toàn bộ mã nguồn.)

Yêu cầu hệ thống

Gói Health Center API yêu cầu phiên bản Eclipse tối thiểu là 3.4 hay 4.x.

Thử nghiệm ứng dụng

Trong Phần 1, bạn đã thử nghiệm ứng dụng, tạo ra các điều kiện tắc nghẽn. Trong bài này, chúng ta sẽ thay đổi ứng dụng một chút, thêm vào một vài tính năng để ép CPU. Xem mục Tải về để lấy mã nguồn. Liệt kê 1 minh họa một đoạn chương trình:

Liệt kê 1. Đoạn mã nguồn mới cho GenerateDeadLock
private class runSlowMethods extends Thread {

   public void run() {
      SlowClassAndMethod1 sCAM1 = new SlowClassAndMethod1();
      SlowClassAndMethod2 sCAM2 = new SlowClassAndMethod2();

      sCAM1.start();
      sCAM2.start();
   }

   private class SlowClassAndMethod1 extends Thread {

      public void run() {
         while (true) {
            slowMethod1();
            try {
               Thread.sleep(2000);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }

      private void slowMethod1() {
         String largeString = new String("a string to add");
         for (int i = 0; i < 1000000; i++) {
            largeString.concat(largeString);
         }

      }
   }

   private class SlowClassAndMethod2 extends Thread {

      public void run() {
         while (true) {
            slowMethod2();
            try {
               Thread.sleep(2000);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }

      private void slowMethod2() {
         HashMap map = new HashMap();
         String largeString = new String("another string to add");
         for (int i = 0; i < 1000000; i++) {
            map.put(i, largeString);
            largeString.concat(largeString);
         }

      }

Khởi động chương trình này với trình Health Center agent được đính kèm. Để khởi động ứng dụng với agen sử dụng phiên bản Java 5 SR10 hoặc mới hơn, Java 6 SR5 hoặc mới hơn, và Java 7, ta dùng dòng lệnh sau (xem Hình 1):

java -Xhealthcenter GenerateDeadlock
Hình 1. Khởi chạy ứng dụng
Ảnh chụp cài đặt ứng dụng từ dòng lệnh

Để khởi chạy ứng dụng với agent sử dụng phiên bản Java 5 SR9 hay cũ hơn, hoặc Java 6 SR4 hay cũ hơn, ta dùng dòng lệnh sau:

java -agentlib:healthcenter -Xtrace:output=healthcenter.out GenerateDeadlock

Bạn có thể tải về IBM developer kits (gói phát triển của IBM).

Lập trình ứng dụng giám sát nâng cao

Để chỉnh sửa ứng dụng DeadlockDemo mà bạn đã tạo ra ở Phần 1, hãy mở tệp Application.java (xem Hình 2):

Hình 2. Mở Application.java
Ảnh chpụ plug-in application.java

Thay thế tất cả mã trong tệp Application.java bằng đoạn mã nguồn bên dưới (xem mục Tải về). Liệt kê 2 hiển thị đoạn mã nguồn:

Liệt kê 2. Đoạn mã nguồn thay thế trong tệp Application.java
private class ProfileApplication extends Thread {

   String methodTree = null;

   public void run() {

      try {
         Thread.sleep(10000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }

      while (keepRunning) {
         analyzeMethods();
         try {
            Thread.sleep(2000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private void analyzeMethods() {
      ProfilingData profilingData;
      profilingData = hcMon.getProfilingData();

      if (profilingData == null) {
         return;
      }

      MethodProfileData[] mPD = profilingData.getProfilingEvents();
      if (mPD != null) {

         final SimpleProfileData[] sPD = new SimpleProfileData[mPD.length];
         int index = 0;
         for (MethodProfileData mP : mPD) {
            methodTree = new String();
            sPD[index] = new SimpleProfileData();
            sPD[index].setCount(mP.getMethodSampleCount());
            sPD[index].setMethodName(mP.getMethodName());
            MethodProfilingNode[] mPN = mP.getCallingMethods();
            for (MethodProfilingNode node : mPN) {
               if (node instanceof MethodProfilingNode) {
                  walkProfileTree(node);
               }
            }
            sPD[index].setMethodTree(methodTree);
            index++;
         }

         Arrays.sort(sPD);

         display.asyncExec(new Runnable() {
            public void run() {

               profileText.setText("method: "
                     + sPD[0].getMethodName()
                     + "\n		sample count:  "
                     + sPD[0].getCount() + "\n"
                     + sPD[0].getMethodName()
                     + sPD[0].getMethodTree());
               shell.redraw();
            }
         });

      }
   }

Đoạn mã này khác với đoạn mã cũ, nhưng hầu hết các thay đổi là để cài đặt hiển thị và áp dụng hành vi đúng cho ứng dụng. Thật ra đoạn mã Health Center API chỉ có thêm lời gọi các phương thức dữ liệu hồ sơ cá nhân mà bạn sẽ xem xét sau này.


Profiling dữ liệu

Health Center sử dụng một profiler dựa vào mẫu, cung cấp khung nhìn của tất cả các phương thức mà ứng dụng của bạn đang sử dụng. Profiler hữu ích cho việc xác định sự tắc nghẽn hiệu năng bởi vì ứng dụng của bạn có thể dành quá nhiều thời gian trong một phương thức duy nhất, gây ra vấn đề về hiệu năng.

Để truy cập dữ liệu profiling, ta sử dụng cách gọi tương tự cách truy cập luồng dữ liệu:

ProfilingData profilingData = HealthCenter.getProfilingData();

Lớp ProfilingData có các phương thức cho phép truy cập vào tất cả phương thức mẫu, số lượng mẫu của chúng, và phân cấp lời gọi.

Phương thức getProfilingEvents() trả về một mảng MethodProfileData, có một đầu vào cho mỗi phương thức mẫu. Với mỗi phương thức đã lấy mẫu, bạn có thể lấy số lượng mẫu với phương thức getMethodSampleCount(), lấy tên của phương thức với getMethodName(), và các phương thức được gọi với getCallingMethods().

Sử dụng các phương thức này để sinh ra sự phân cấp lời gọi của phương thức lấy mẫu tốt nhất. Sau đó, sử dụng thông tin đó để tinh chỉnh hiệu năng của ứng dụng.


Giám sát tắc nghẽn và phương thức Profiling

Bây giờ bạn đã có ứng dụng theo dõi tắc nghẽn (deadlock) và profiling với chương trình giám sát tắc nghẽn đang chạy ngầm. Chạy chương trình giám sát tắc nghẽn và profiling để xem các thông điệp "Deadlock detected" trên cửa sổ theo dõi của ứng dụng (xem Hình 3):

Hình 3. Giám sát tắc nghẽn
Hình ảnh theo dõi tắc nghẽn trong ứng dụng

Rõ ràng là bạn đã có dữ liệu. Bây giờ là lúc để hiểu ý nghĩa của nó.


Dữ liệu profiling cho thấy điều gì

Trong bảng trên cùng, thông tin sample count tăng lên khi ứng dụng chạy, cho thấy rằng phương thức này sử dụng nhiều chu kỳ CPU nhất. Liệt kê 3 hiển thị thông tin xuất ra của phương thức trên cùng:

Liệt kê 3. Thông tin xuất ra của phương thức trên cùng
profileText.setText("method: "
   + sPD[0].getMethodName()
   + "\n		sample count:  "
   + sPD[0].getCount() + "\n"
   + sPD[0].getMethodName()
   + sPD[0].getMethodTree());

Bạn còn có thể thay đổi để có kết quả từ nhiều phương thức bằng cách lặp tất cả phần tử trong mảng sPD.

Khi profiler chạy trong Health Center, một phương thức sẽ lấy số đếm nếu nó chạy mã Java nhiều lần. Phương thức càng có nhiều mẫu thì càng thực hiện nhiều lần. Số mẫu có thể không phản ánh mức độ thường xuyên mà phương thức được gọi. Nó chỉ ra phương thức hoạt động bao nhiêu lần so với các phương thức khác trong ứng dụng.

Trong ví dụ này, điển hình là bạn có thể thấy phương thức java.util.HashMap.rehash(int). Nó gọi tới stack (nơi mà nó được gọi) chỉ ra nguồn gốc của lời gọi trong phương thức GenerateDeadlock$runSlowMethods$SlowClassAndMethod2.run().

Hãy xem xét lời gọi tiếp theo, phương thức run() gọi phương thức GenerateDeadlock$runSlowMethods$SlowClassAndMethod2.slowMethod2(), chịu trách nhiệm cho lời gọi java.util.HashMap.put. Lần lượt gọi đến rehash().

Nếu bạn nhìn vào phương thức slowMethod2() trong ứng dụng tắt nghẽn, bạn có thể nhìn thấy một vòng lặp đặt đầu vào bên trong một HashMap (xem Liệt kê 4):

Liệt kê 4. Vòng lặp đặt đầu vào bên trong một HashMap
private void slowMethod2() {
   HashMap map = new HashMap();
   String largeString = new String("another string to add");
   for (int i = 0; i < 1000000; i++) {
      map.put(i, largeString);
      largeString.concat(largeString);
   }
}

Bạn có thể chú giải vòng lặp trong phương thức, như trong Liệt kê 5:

Liệt kê 5. Chú giải vòng lặp
   private void slowMethod2() {
      HashMap map = new HashMap();
      String largeString = new String("another string to add");
//      for (int i = 0; i < 1000000; i++) {
//         map.put(i, largeString);
//         largeString.concat(largeString);
//      }
   }

Nếu bạn chạy lại ứng dụng kiểm tra, sau đó công cụ tắc nghẽn và profiling, hãy lưu ý rằng vấn đề đã được sửa. Một phương thức mới xuất hiện trong bảng profiling (xem Hình 4):

Hình 4. Vấn đề đã được sửa—phương thức mới xuất hiện
Ảnh chụp một phương pháp mới trong panel điều khiển

Quá trình này—xác định các phương thức quan trọng và giúp giải quyết tắc nghẽn—bây giờ chúng ta có thể bắt đầu lại.


Kết luận

Loại bài này cho ta kiến thức cơ bản để bắt đầu với Health Center API. Bạn có thể ứng dụng kĩ thuật này để mở rộng và sử dụng nhiều dữ liệu bên trong Health Center. Ví dụ, bạn có thể sử dụng API để lấy chi tiết trên các phương thức của WebSphere® chỉ khi chúng bắt đầu bị tắc nghẽn, hay kích hoạt dump hệ thống khi ứng dụng tràn bộ nhớ.


Tải về

Mô tảTênKích thước
Source code for articlej-healthcareapi2-source.zip3KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Công nghệ Java
ArticleID=941841
ArticleTitle=Phát triển Java 2.0: Theo dõi ứng dụng Java với Health Center API, Phần 2
publish-date=08222013