[java] Java와 C / C ++ 간의 프로세스 간 통신을위한 가장 빠른 (낮은 지연) 방법

TCP 소켓을 통해 C / C ++로 개발 된 “서버”에 연결하는 Java 앱이 있습니다.

앱과 서버는 모두 동일한 시스템 인 Solaris 상자에서 실행됩니다 (하지만 결국 Linux로 마이그레이션하는 것을 고려 중입니다). 교환되는 데이터 유형은 간단한 메시지입니다 (로그인, 로그인 ACK, 클라이언트 요청, 서버 응답). 각 메시지의 길이는 약 300 바이트입니다.

현재 우리는 소켓을 사용하고 있으며 모든 것이 괜찮지 만 IPC 방법을 사용하여 데이터를 교환하는 더 빠른 방법 (낮은 대기 시간)을 찾고 있습니다.

나는 인터넷을 조사해 왔고 다음 기술에 대한 언급을 찾았습니다.

  • 공유 메모리
  • 파이프
  • 대기열
  • DMA (Direct Memory Access)라고하는 것

하지만 각각의 성능에 대한 적절한 분석을 찾을 수 없었습니다. JAVA와 C / C ++ 모두에서 구현하는 방법 (서로 대화 할 수 있도록)도 찾을 수 없었습니다. 제가 상상할 수있는 파이프를 제외하고는 말입니다.

누구든지이 맥락에서 각 방법의 성능 및 타당성에 대해 언급 할 수 있습니까? 유용한 구현 정보에 대한 포인터 / 링크가 있습니까?


편집 / 업데이트

내가 여기에 얻은 의견 및 답변에 따라 파이프 위에 구축 된 것처럼 보이는 Unix 도메인 소켓에 대한 정보를 발견했으며 전체 TCP 스택을 저장합니다. 플랫폼에 따라 다르므로 JNI 또는 juds 또는 junixsocket 으로 테스트 할 계획입니다 .

다음으로 가능한 단계는 파이프를 직접 구현 한 다음 메모리를 공유하는 것입니다. 비록 추가 수준의 복잡성에 대해 경고를 받았지만 …


당신의 도움을 주셔서 감사합니다



답변

Corei5 2.8GHz에서 Java의 지연 시간을 테스트했습니다. 단일 바이트 전송 / 수신, 2 개의 Java 프로세스가 방금 생성되었으며 작업 세트와 함께 특정 CPU 코어를 할당하지 않았습니다.

TCP         - 25 microseconds
Named pipes - 15 microseconds

이제 taskset 1 java Srv 또는 taskset 2 java Cli 와 같이 코어 마스크를 명시 적으로 지정합니다 .

TCP, same cores:                      30 microseconds
TCP, explicit different cores:        22 microseconds
Named pipes, same core:               4-5 microseconds !!!!
Named pipes, taskset different cores: 7-8 microseconds !!!!

그래서

TCP overhead is visible
scheduling overhead (or core caches?) is also the culprit

동시에 Thread.sleep (0) (strace가 보여 주듯이 단일 sched_yield () Linux 커널 호출이 실행 됨)은 0.3 마이크로 초가 걸립니다. 따라서 단일 코어로 예약 된 명명 된 파이프에는 여전히 많은 오버 헤드가 있습니다.

일부 공유 메모리 측정 :
2009 년 9 월 14 일 – Solace Systems는 오늘 자사의 통합 메시징 플랫폼 API가 공유 메모리 전송을 사용하여 700 나노초 미만의 평균 대기 시간을 달성 할 수 있다고 발표했습니다.
http://solacesystems.com/news/fastest-ipc-messaging/

추신-다음날 메모리 매핑 파일의 형태로 공유 메모리를 시도했습니다. 바쁜 대기가 허용되는 경우 다음과 같은 코드로 단일 바이트를 전달하는 대기 시간을 0.3 마이크로 초로 줄일 수 있습니다.

MappedByteBuffer mem =
  new RandomAccessFile("/tmp/mapped.txt", "rw").getChannel()
  .map(FileChannel.MapMode.READ_WRITE, 0, 1);

while(true){
  while(mem.get(0)!=5) Thread.sleep(0); // waiting for client request
  mem.put(0, (byte)10); // sending the reply
}

참고 : Thread.sleep (0)이 필요하므로 두 프로세스가 서로의 변경 사항을 볼 수 있습니다 (아직 다른 방법은 모릅니다). 2 개의 프로세스가 작업 세트와 동일한 코어로 강제되면 지연 시간이 1.5 마이크로 초가됩니다. 이는 컨텍스트 전환 지연입니다.

PPS-0.3 마이크로 초는 좋은 수치입니다! 다음 코드는 기본 문자열 연결 만 수행하는 동안 정확히 0.1 마이크로 초가 걸립니다.

int j=123456789;
String ret = "my-record-key-" + j  + "-in-db";

PPPS-이것이 너무 주제에서 벗어난 것이 아니기를 바라지 만, 마침내 Thread.sleep (0)을 정적 휘발성 int 변수 (이렇게 할 때 JVM이 CPU 캐시를 플러시하는 일이 발생 함)를 증가시켜 바꾸려고 시도하고 획득했습니다-기록! – 72 나노초 지연 자바 대 자바 프로세스 통신 !

그러나 동일한 CPU 코어로 강제 될 때 휘발성 증가 JVM은 서로 제어를 양보하지 않으므로 정확히 10 밀리 초의 지연 시간이 발생합니다. Linux 시간 퀀텀은 5ms 인 것 같습니다. 따라서 예비 코어가있는 경우에만 사용해야합니다. 그렇지 않으면 sleep (0)이 더 안전합니다.


답변

DMA는 하드웨어 장치가 CPU를 중단하지 않고 물리적 RAM에 액세스 할 수있는 방법입니다. 예를 들어 일반적인 예는 디스크에서 RAM으로 바이트를 직접 복사 할 수있는 하드 디스크 컨트롤러입니다. 따라서 IPC에는 적용되지 않습니다.

공유 메모리와 파이프는 모두 최신 OS에서 직접 지원됩니다. 따라서 매우 빠릅니다. 큐는 일반적으로 추상화입니다. 예를 들어 소켓, 파이프 및 / 또는 공유 메모리 위에 구현됩니다. 이것은 느린 메커니즘처럼 보일 수 있지만 대안은 그러한 추상화 만드는 것입니다.


답변

이 질문은 얼마 전에 질문되었지만 일반적인 지연 시간 200ns와 처리량 20M / 초를 지원하는 https://github.com/peter-lawrey/Java-Chronicle에 관심이있을 수 있습니다 . 프로세스간에 공유되는 메모리 매핑 파일을 사용합니다 (데이터를 유지하는 가장 빠른 방법으로 데이터를 유지함).


답변

다음은 다양한 IPC 전송에 대한 성능 테스트를 포함하는 프로젝트입니다.

http://github.com/rigtorp/ipc-bench


답변

네이티브 액세스 사용을 고려한 적이 있다면 (애플리케이션과 “서버”가 모두 동일한 시스템 에 있기 때문에) JNA를 고려하십시오 . 처리 할 표준 코드가 적습니다.


답변

늦게 도착했지만 Java NIO를 사용하여 핑 대기 시간을 측정하는 데 전념 하는 오픈 소스 프로젝트 를 지적하고 싶었습니다 .

블로그 게시물 에서 더 자세히 알아보고 설명했습니다 . 결과는 다음과 같습니다 (나노 단위의 RTT) :

Implementation, Min,   50%,   90%,   99%,   99.9%, 99.99%,Max
IPC busy-spin,  89,    127,   168,   3326,  6501,  11555, 25131
UDP busy-spin,  4597,  5224,  5391,  5958,  8466,  10918, 18396
TCP busy-spin,  6244,  6784,  7475,  8697,  11070, 16791, 27265
TCP select-now, 8858,  9617,  9845,  12173, 13845, 19417, 26171
TCP block,      10696, 13103, 13299, 14428, 15629, 20373, 32149
TCP select,     13425, 15426, 15743, 18035, 20719, 24793, 37877

이것은 받아 들여지는 대답의 선을 따른 것입니다. System.nanotime () 오류 (아무것도 측정하지 않음으로 추정 됨)는 약 40 나노에서 측정되므로 IPC의 경우 실제 결과가 더 낮을 수 있습니다. 즐겨.


답변

네이티브 프로세스 간 통신에 대해서는 잘 모르지만 JNI 메커니즘을 사용하여 액세스 할 수있는 네이티브 코드를 사용하여 통신해야한다고 생각합니다. 따라서 Java에서 다른 프로세스와 통신하는 기본 함수를 호출합니다.