2010-06-01 7 views
1

나는 이것이 어둠 속에서 절대적으로 일어난다는 것을 알고있다. 그러나 우리는 절대적으로 당혹 스럽다.자바에서 시작된 펄은 영원히 걸린다

Java (1.5)에서 실행되는 perl (5.8.6) 스크립트가 완료하는 데 1 시간 이상 걸립니다. 동일한 스크립트가 명령 줄에서 수동으로 실행될 때 완료하는 데 12 분이 걸립니다. 이것은 Linux 호스트에 있습니다.

로깅은 두 경우 모두 동일하며 스크립트는 두 경우 모두 동일한 매개 변수로 실행됩니다.

스크립트는 Oracle DB 액세스, 일부 scp 등의 복잡한 작업을 수행하지만 두 경우 모두 똑같은 작업을 수행합니다.

우리는 어려움을 겪고 있습니다. 누구도 비슷한 상황에 빠져 있습니까? 그렇지 않고 동일한 상황에 직면했다면 어떻게 디버깅을 고려할 것입니까?

+5

스크립트가 완료되었거나 한 시간이 지나도 계속 실행 중입니까? 스크립트를 어떻게 실행합니까? 스크립트의 출력 (프로세스 # getInputStream(), 프로세스 # getErrorSteam())을 읽으십니까? 버퍼가 읽히지 않으면 프로세스가 차단 될 수 있음을 기억합니다. – sfussenegger

+0

두 경우 모두 동일한 하드웨어에서 실행됩니까? – Zaid

+0

경과 시간은 어떻게 측정합니까? – LB40

답변

0

이 스레드를 닫으려면 최종 프로세스가 너무 많은 CPU를 소비하는 불량 프로세스였습니다. 명령 줄에서 시작하면 스크립트는 보통 우선 순위를가집니다. Java에서 실행될 때 스크립트의 우선 순위가 낮았고 영원히 실행되었습니다. Java 코드가 스크립트를 실행하는 것이 아니라 대화 형으로 발행 한 SSH를 통해 동일한 명령을 실행한다는 것이 우리를 버렸습니다. 따라서 우리는 우선 순위의 차이를 기대하지 않았습니다.

3

Java 래퍼가 희소 한 리소스를 통해 커다란 경합을 일으키는 다른 것으로 동시에 실행될 가능성을 무시했다고 가정합니다. 좋은. 이 같은 간단한 클래스가있는 경우

:

public class Exec { 
    public static void main(String[] args) throws Throwable{ 
     class Transfer implements Runnable { 
      private final InputStream in; 
      private final OutputStream out; 
      public Transfer(InputStream i, OutputStream o){ 
       in = i; 
       out = o; 
      } 
      public void run(){ 
       try { 
        for (int i; (i = in.read()) != -1;) out.write(i); 
        out.close(); 
        in.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     Process proc = new ProcessBuilder(args).start(); 
     new Thread(new Transfer(System.in, proc.getOutputStream())).start(); 
     new Thread(new Transfer(proc.getInputStream(), System.out)).start(); 
     new Thread(new Transfer(proc.getErrorStream(), System.err)).start(); 
     System.exit(proc.waitFor()); 
    } 
} 

을 ... 그리고 당신이 time perl script.pl insert args heretime java Exec perl script.pl insert args here 비교, 무슨 일이? 세계가 정상적인 경우, 두 번째 자바가 시작될 때까지 몇 초가 더 걸리는 것을 제외하고는 같은 시간이 걸릴 것입니다. 그렇다면 점차적으로 Exec 클래스를 배포 환경에 점점 더 비슷하게 적응 시키십시오. , 그리고 그것이 정말로 오랜 시간이 걸리기 시작할 때를보십시오.

위의 경우 이 실제로 더 오래 걸리면 Perl 스크립트에 미친 것처럼 로깅을 시작하십시오. 그러면 어떤 작업이 더 오랜 시간이 걸리는지 알 수 있습니다. 그리고 btw, Java wrapper도 로그인하십시오. 그래서 펄 시작이 정말로 오랜 시간이 걸리는지 알 수 있습니다.

2

하나의 가능성은 충분한 메모리가없는 시스템에서 큰 Java 응용 프로그램과 큰 Perl 응용 프로그램을 실행하여 시스템이 스 래시되고 있다는 것입니다.

topvmstat -5iostat -5 등의 모니터링 유틸리티를 사용하여 속도가 일부 OS 수준의 병리와 일치하는지 확인하는 것이 좋습니다.

4

stdout/stderror 스트림을 플러시하지 않으면 콘솔 출력을 생성하는 하위 프로 세스가 차단 (및 교착 상태) 될 수 있습니다. @ gustafc, posed 코드는 stdout/stderror에 쓰기를 시도 할 때 하위 프로세스를 차단하고 스트림에 공간이 없으며 스트림이 java에 의해 처리되지 않습니다.

Process p = startProcess(); 

final InputStream stdout = p.getInputStream(); 
final InputStream sterr = p.getErrorStream(); 

new Thread() { 
public void run() { 
    int c; 
    while ((c = sterr.read()) != -1) { 
    System.out.print((char)c); 
    } 
} 
}.start(); 

new Thread() { 
public void run() { 
    int c; 
    while ((c = sterr.read()) != -1) { 
    System.out.print((char)c); 
    } 
} 
}.start(); 
+0

그에 따라 내 코드가 업데이트됩니다. (그리고 우리가 US-ASCII를 사용하고 있다고 가정하지는 않습니다) – gustafc

+0

아, 이것은 예시적인 예를 의미합니다. 대부분의 사람들은 StreamFluser 클래스를 만들고 1 개의 2를 인스턴스화합니다. – Justin