2017-11-21 1 views
0

ich eine sehr einfache .proto-Datei erstellt habe:Google Protocol Buffer, schnell auf Windows, langsam auf Ubuntu

syntax = "proto2"; 


package Metadata; 


option java_package = "metadata"; 
option java_outer_classname = "Metadata"; 
option optimize_for=SPEED; 
message PutMessage { 
optional string key =1; 
optional int64 dt = 2; 
} 

Ich habe ein einfaches Client-Server-Programm erstellen, die Server-Client-Nachricht hallt. Alle Meldungen sind PutMessage:

Server:

public class Server { 
public static void main(String args[]) throws IOException, InterruptedException { 
ServerSocket ss = new ServerSocket(8080); 
System.out.println("Listening for client"); 
Socket socket = ss.accept(); 
System.out.println("Server Results: "); 
while (true) { 
Long parseStart = System.nanoTime(); 
PutMessage sm = PutMessage.parseDelimitedFrom(socket.getInputStream()); 
Long parseEnd = System.nanoTime(); 

Long writeStart = System.nanoTime(); 
sm.writeDelimitedTo(socket.getOutputStream()); 
Long writeEnd = System.nanoTime(); 

System.out.println("Parse time: " + (parseEnd - parseStart)); 
System.out.println("Write time: " + (writeEnd - writeStart)); 

} 


} 
} 

Auftraggeber:

public class Client { 
public static void main (String args[]) throws IOException, InterruptedException{ 
Socket socket = new Socket("127.0.0.1", 8080); 
int A = new Integer(args[0]); 
PutMessage cm = PutMessage.newBuilder().setDt(3434).setKey("sdfwsdf").build(); 
System.out.println("Client Results7: "); 
for (int i=0;i < A; i++){ 
Long writeStart = System.nanoTime(); 
cm.writeDelimitedTo(socket.getOutputStream()); 
Long writeEnd = System.nanoTime(); 

Long parseStart = System.nanoTime(); 
cm.parseDelimitedFrom(socket.getInputStream()); 
Long parseEnd = System.nanoTime(); 

System.out.println("Write time: " + (writeEnd - writeStart)); 
System.out.println("Parse time: " + (parseEnd - parseStart)); 
} 
} 
} 

Wenn ich laufen Client und Server unter Windows ist es sehr schnell. Aber wenn ich auf Ubuntu laufen, dauert es eine lange Zeit (70 (ms)) für den Server den Client Nachricht zu analysieren: Das sind einige Ergebnisse sind, wenn ich 3 an den Client übergeben:

Alle in Nanosekunden

Fenster:

Client Results: 
Write time: 54401508 
Parse time: 95818962 
Write time: 279563 
Parse time: 201593 
Write time: 200568 
Parse time: 138500 



Server Results: 
Parse time: 207099065 
Write time: 42572640 
Parse time: 20808241 
Write time: 156966 
Parse time: 209801 
Write time: 124649 

Ubuntu:

Client Results: 
Write time: 31205019 
Parse time: 86399222 
Write time: 101132 
Parse time: 40619478 
Write time: 214496 
Parse time: 79164985 


Server Results: 
Parse time: 183947743 
Write time: 25819286 
Parse time: 28680184 
Write time: 292955 
Parse time: 79299932 
Write time: 298012 

ich fand, dass, wenn ich setDt aus setzen Nachricht zu entfernen und wenn es nur setKey ist, es ist schnell auf zu Ubuntu. Aber ich muss dt haben. Ich habe keine Ahnung, warum es unter Windows schnell ist und Ubuntu langsamer macht. Ich dachte, vielleicht ist meine Maschine anders, aber ohne setDt ist es schnell auf Ubuntu, also ist das Problem nicht die Hardware.

Ich habe auch Proto3, gleiche Ergebnisse versucht. Jede Hilfe wird sehr geschätzt.

Aktualisieren: Beide Betriebssysteme sind 64-Bit. Java-Versionen sind:

Ubuntu:

java version "1.8.0_66" 
Java(TM) SE Runtime Environment (build 1.8.0_66-b17) 
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode) 

Fenster:

java version "1.8.0_151" 
Java(TM) SE Runtime Environment (build 1.8.0_151-b12) 
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode) 

Dank

aktualisieren: ich das Experiment auf zwei AWS EC2-Instanzen umgestrickt. Ein Windows und das andere Amazon Linux. Ich habe dieses Mal Ubuntu nicht benutzt, aber ich habe die gleichen Ergebnisse bekommen. Wiederum habe ich viel schnellere Ergebnisse unter Windows bekommen. Es ist wirklich komisch!

+0

Welche JVM verwenden Sie auf der Linux-Seite und auf der Windows-Seite? Verwenden Sie eine Server- oder Client-VM? Wärst du die JVM auf (sieht nicht so aus)? –

+2

Siehe auch: [Wie schreibe ich eine korrekte Microbenchmark in Java?] (Https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). –

+0

Der Code, der Benchmark ist für Windows und Ubuntu der gleiche, warum ist einer schnell, der andere ist langsam? – spartanHp

Antwort

0

Sie messen die IO-Zeit, nicht die Parse-Zeit. Wenn Sie die Parse-Zeit messen möchten, analysieren Sie sie von einem Byte-Array oder einem ByteArrayInputStream.

Der Unterschied zwischen den Fenstern und Ubuntu in diesem speziellen Fall von der IO Umsetzung stammen kann, um weitere Daten für eine bestimmte Zeit warten, bevor er (um die Anzahl Overhead zu reduzieren) übergeben wird. Ich würde versuchen, den Stream auf dem Server zu schließen oder zu leeren - oder einfach einige zusätzliche Daten dorthin zu schicken.

1

Ich fand heraus, statt writDelimetedTo und parseDelimitedFrom aufrufen, wenn wir Bytes schreiben, gibt es keine Verzögerung:

Server:

public class CodedServer { 
    public static void main(String args[]) throws IOException, InterruptedException { 
     ServerSocket ss = new ServerSocket(8080); 
     System.out.println("Listening for client8"); 
     Socket socket = ss.accept(); 
     System.out.println("Server Results: "); 
     CodedOutputStream out = CodedOutputStream.newInstance(socket.getOutputStream()); 
     CodedInputStream in = CodedInputStream.newInstance(socket.getInputStream()); 
     while (true) { 

      Long parseStart = System.nanoTime(); 
      int size = in.readInt32(); 
      byte[] result = in.readRawBytes(size); 
      PutMessage cm = PutMessage.parseFrom(result); 
      Long parseEnd = System.nanoTime(); 

      Long writeStart = System.nanoTime(); 
      out.writeInt32NoTag(cm.getSerializedSize()); 
      cm.writeTo(out); 
      out.flush(); 
      Long writeEnd = System.nanoTime(); 

      System.out.println("Parse time: " + (parseEnd - parseStart)); 
      System.out.println("Write time: " + (writeEnd - writeStart)); 

     } 

    } 
} 

Auftraggeber:

public class CodedClient { 
    public static void main (String args[]) throws IOException, InterruptedException{ 
     Socket socket = new Socket(args[0], 8080); 
     int A = new Integer(args[1]); 
     PutMessage cm = PutMessage.newBuilder().setDt("sdfsdfsdf").setKey("Test Stringdfgdsfgsdfgsdfgsdfgsdfgsdfgsdfgsdfgsdfgsdfgsdfgsdfg").build(); 

     CodedOutputStream out = CodedOutputStream.newInstance(socket.getOutputStream()); 
     CodedInputStream in = CodedInputStream.newInstance(socket.getInputStream()); 

     System.out.println("Client Results9: "); 
     for (int i=0;i < A; i++){ 
      Long writeStart = System.nanoTime(); 
      out.writeInt32NoTag(cm.getSerializedSize()); 
      cm.writeTo(out); 
      out.flush(); 
      Long writeEnd = System.nanoTime(); 


      Long parseStart = System.nanoTime(); 
      int size = in.readInt32(); 
      byte[] result = in.readRawBytes(size); 
      cm = PutMessage.parseFrom(result); 
      Long parseEnd = System.nanoTime(); 

      System.out.println("Write time: " + (writeEnd - writeStart)); 
      System.out.println("Parse time: " + (parseEnd - parseStart)); 
     } 
     System.out.println(cm.toString()); 
    } 
} 

Ich bin glücklich, um eine Lösung zu finden, aber ich frage mich, warum die Implementierung von zwei Standardfunktionen durch den Google-Protokollpuffer eine so erhebliche Verzögerung verursachen sollte?

Verwandte Themen