2009-06-23 15 views
5

Tengo una situación desconcertante y necesitaría una opinión experta sobre la causa del fenómeno que se explica a continuación. Hace un par de semanas, realicé una sesión titulada "Una visión general de .NET para desarrolladores de Java" y como parte de ella escribí una clase rápida C# (3.5 framework) para leer desde un archivo y escribir en otro archivo línea por línea (en una iteración). Como mi público era desarrollador de Java, tenía el mismo código en una clase de Java para la comparación de lado a lado. Sin embargo, cuando ejecuté estas clases en la misma máquina, para mi sorpresa, el código java se ejecutó dos veces más rápido que el código C#. He intentado muchas optimizaciones en el código C# para reducir la brecha, pero no pude tener éxito. Tiene que haber una explicación y estoy buscando a alguien que pueda explicar la causa. Adjunto el código fuente de ambas clases para su referencia.punto de referencia y la causa de la diferencia entre C# y java


clase Java

public class ReadWriteTextFile { 

    static public String getContents(File aFile, String OutPutFileName) { 
    StringBuilder contents = new StringBuilder(); 

    try { 
     BufferedReader input = new BufferedReader(new FileReader(aFile)); 
     FileReader x = new FileReader(aFile); 
     try { 
     String line = null; 
     while ((line = input.readLine()) != null){ 
       setContents(OutPutFileName, line + System.getProperty("line.separator")); 
     } 
     } 
     finally { 
     input.close(); 
     } 
    } 
    catch (IOException ex){ 
     ex.printStackTrace(); 
    } 

    return contents.toString(); 
    } 

    static public void setContents(String FileName, String aContents) 
           throws FileNotFoundException, IOException { 
    try { 
     FileWriter fstream = new FileWriter(FileName, true); 
     BufferedWriter out = new BufferedWriter(fstream); 
     out.write(aContents); 
      out.close(); 
    } catch (Exception xe) { 
     xe.printStackTrace(); 
    } 
    } 
    public static void main (String[] aArguments) throws IOException { 

    System.out.println(getDateTime() + ": Started"); 
    File testFile = new File("C:\\temp\\blah.txt"); 
     String testFile2 = "C:\\temp\\blahblah.txt"; 

    for(int i=0; i<100; i++){ 
     getContents(testFile, testFile2); 
    } 

    System.out.println(getDateTime() + ": Ended"); 

    } 

    private synchronized static String getDateTime() { 
     DateFormat dateFormat = new SimpleDateFormat(
             "yyyy/MM/dd HH:mm:ss"); 
     Date date = new Date(); 
     return dateFormat.format(date); 
    } 
} 

clase C#

class ReadWriteTextFile 
{ 
    static void Main(string[] args) 
    { 
     System.Diagnostics.Trace.WriteLine(getDateTime() + ": Started"); 
     String testFile = "C:\\temp\\blah.txt"; 
     String testFile2 = "C:\\temp\\blahblah.txt"; 
     for(int i=0; i<100; i++){ 
      getContents(testFile, testFile2); 
     } 
     System.Diagnostics.Trace.WriteLine(getDateTime() + ": Ended"); 
    } 

    static public void getContents(String sourceFile, String targetFile) {  
     try { 
      using (StreamReader r = File.OpenText(sourceFile)) 
      { 
       String line; 
       while ((line = r.ReadLine()) != null) 
       { 
        setContents(targetFile, line); 
       } 
       r.Close(); 
      } 
    } 
    catch (IOException ex){ 
     Console.WriteLine(ex.StackTrace); 
    } 
    } 

    static public void setContents(String targetFile, String aContents) 
    { 

    try { 
     //FileStream fsO = new FileStream(targetFile, FileMode.Append); 
     //StreamWriter w = new StreamWriter(fsO); 
     FileStream fs = new FileStream(targetFile, FileMode.Append, 
           FileAccess.Write, FileShare.None); 
     using (StreamWriter w = new StreamWriter(fs)) 
     { 
      w.WriteLine(aContents + "\n"); 
     } 
    } catch (Exception xe) { 
     Console.WriteLine(xe.StackTrace); 
    } 
    } 

    private static String getDateTime() { 
     DateTime dt = DateTime.Now; 
     return dt.ToString("yyyy/MM/dd HH:mm:ss"); 
    } 
} 

+1

Quizás es un caso simple de 'java puede hacer esto en particular más rápido'. – karim79

+0

¿Qué JDK estás usando? ¿Alguna optimización activada? – duffymo

+1

Intente volver a ejecutar la versión C# inmediatamente después de ejecutarlo. –

Respuesta

8

Por un lado: en Java que está utilizando codificación por defecto de la plataforma. Esa bien puede ser una codificación fija de "un byte por carácter", que claramente va a ser más simple que usar UTF-8, que .NET realiza de forma predeterminada.

Además, se está escribiendo dos nuevas líneas en .NET, y sólo uno en Java.

Una cosa que debes comprobar es si estás vinculado a la CPU o IO. Me gustaría esperar esto para ser IO-bound, pero ciertamente me he sorprendido antes de ahora.

Finalmente, debe ejecutar cada prueba después de un reinicio para tratar de eliminar las cachés de disco de la ecuación en la medida de lo posible.

+0

¿Cómo desactivo la codificación UTF- * en .NET y por qué dice que estoy escribiendo dos líneas en la versión .NET ???? ¿Cómo puedo verificar si estoy vinculado a la CPU o a IO? –

+1

Datos de JS: Jon Skeet dejó MS y de repente todo el programa C# corrió dos veces más lento que antes :) – akarnokd

+2

Llamas a WriteLine * y * agregando "\ n". Especifique la codificación utilizando la sobrecarga del constructor para StreamWriter que toma uno. Use Encoding.Default para que funcione como la versión de Java. Cree un nuevo StreamReader en lugar de llamar a File.OpenText, de esa manera puede especificar la codificación allí también. –

3

No veo ningún problema de código aquí. Algunas posibilidades: ¿ejecutó el código C# en modo de depuración quizás? Hubo un problema con el almacenamiento en caché de archivos. El archivo de datos C# operaba en un área de disco muy fragmentada. No esperaría la mitad de velocidad para un programa de C# tan simple como este.

Edición: Probé ambas versiones en un blah.txt de 10439 bytes. El archivo generado tenía 1 043 900 bytes de longitud. tiempo

C# (CTRL + F5) fue de 18 segundos
tiempo C# (F5) fue de 22 segundos de tiempo de
Java fue de 17 segundos.

Ambas aplicaciones consumieron aproximadamente 40% de tiempo de CPU, la mitad de ellas fue tiempo de kernel.

Edit2: El límite de la CPU se debe a que el código está constantemente abriendo, cerrando y escribiendo pequeños fragmentos de datos. Esto provoca una gran cantidad de transiciones nativas administradas y de kernel de usuario.

Mi sistema de especificaciones: Core 2 Duo a 2,4 GHz, 2 GB de RAM a 800 MHz, WinXP SP3

+0

Ejecuté el código C# tanto en el modo de depuración como en el de liberación con tiempos similares. –

+0

Por el comentario anterior, ¿quiere decir que lo ejecutó * lo * compiló con depuración y publicación, o que lo ejecutó en el depurador y no en el depurador? Este último hace * mucho * más diferencia que el anterior, en mi experiencia. Desde Visual Studio, presiona Ctrl-F5 en lugar de F5. –

+0

Déjame ser claro ....Corrí ambos presionando F5 (depurar) y Ctrl + F5 (ejecutar sin depuración) –

2

La parte lenta de los puntos de referencia se ve como si es en un solo archivo se abre en varias ocasiones, decorado, una pequeña y escritura cerrado de nuevo. No es un punto de referencia útil.Las diferencias obvias serían cuán grandes son los búferes (con una sola escritura, en realidad no es necesario) y si el archivo resultante está sincronizado con el disco.

+0

Usted sabe de cualquier IO simple marca de funcionamiento de operación entre java y C#, si necesito demostrarlo a la gente. –

+0

Elija algo * realista *. Por el momento, es probable que su cuello de botella esté abriendo el archivo para anexarlo, lo que no suele ser el cuello de botella en las aplicaciones reales. –

Cuestiones relacionadas