2014-03-26 172 views
0

在测试各种文件大小的加密时,我应该测量以下代码的运行时间。但我认为我使用的方法仅仅是输出CPU的当前计时器,而不是程序的运行时间。这是实施的代码,但我认为我没有做到这一点以纳米秒为单位测量程序的运行时间

long startTime = System.nanoTime(); 

// call function 
obj.callFunction(); 

long endTime = System.nanoTime(); 
long timeDifference = endTime - startTime; 

这是我的实际计划。我应该如何修改计时器代码,以便它反映程序的实际运行时间而不是系统时钟?谢谢!

import javax.crypto.Cipher; 

import java.io.BufferedReader; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.FileReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

import javax.crypto.CipherInputStream; 
import javax.crypto.CipherOutputStream; 
import javax.crypto.spec.SecretKeySpec; 


public class AESJava { 

    public static void main(String[] args) { 


     // returns the current value of the system timer, in nanoseconds 
      System.out.print("time in nanoseconds = "); 
      System.out.println(System.nanoTime()); 


     try { 



      BufferedReader br = new BufferedReader(new FileReader("key.txt")); 
      String key = br.readLine(); 
      br.close(); 
      FileInputStream fis = new FileInputStream("original.txt"); 
      FileOutputStream fos = new FileOutputStream("encrypted.txt"); 
      encrypt(key, fis, fos); 

      FileInputStream fis2 = new FileInputStream("encrypted.txt"); 
      FileOutputStream fos2 = new FileOutputStream("decrypted.txt"); 
      decrypt(key, fis2, fos2); 

     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable { 
     encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os); 
    } 

    public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable { 
     encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os); 
    } 

    public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable { 


     SecretKeySpec dks = new SecretKeySpec(key.getBytes(),"AES"); 
     Cipher cipher = Cipher.getInstance("AES"); 

     if (mode == Cipher.ENCRYPT_MODE) { 
      cipher.init(Cipher.ENCRYPT_MODE, dks); 
      CipherInputStream cis = new CipherInputStream(is, cipher); 
      doCopy(cis, os);   
     } else if (mode == Cipher.DECRYPT_MODE) { 
      cipher.init(Cipher.DECRYPT_MODE, dks); 
      CipherOutputStream cos = new CipherOutputStream(os, cipher); 
      doCopy(is, cos); 
     } 


    } 

    public static void doCopy(InputStream is, OutputStream os) throws IOException { 
     byte[] bytes = new byte[128]; 
     int numBytes; 
     while ((numBytes = is.read(bytes)) != -1) { 
      os.write(bytes, 0, numBytes); 
     } 
     os.flush(); 
     os.close(); 
     is.close(); 
    } 

} 
+1

没有使用底层操作系统的内核统计信息,您的应用程序无法区分差异。如果你多次运行你的代码,你应该得到合理的值。 – PMF

+0

要添加到PMF的建议中,只要代码/数据每次都是相同的,请多次运行它并采取最小的测量,以尽量缩短上下文切换和其他OS功能的时间。 –

+0

可能的重复:http://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java – mok

回答

1

我很困惑,因为你的第一件事情是绝对正确的,但那么你的主要方法不会做你写的东西。它只是打印CPU时间(自纪元以来),并不计算实际的挂墙时间。最简单的方法来改变你的程序是创建一个方法(函数),做你的主要方法,然后只需插入最初的部分。下面是摘录:

private static void doMain(){ 
    try { 
     BufferedReader br = new BufferedReader(new FileReader("key.txt")); 
     String key = br.readLine(); 
     br.close(); 
     FileInputStream fis = new FileInputStream("original.txt"); 
     FileOutputStream fos = new FileOutputStream("encrypted.txt"); 
     encrypt(key, fis, fos); 

     FileInputStream fis2 = new FileInputStream("encrypted.txt"); 
     FileOutputStream fos2 = new FileOutputStream("decrypted.txt"); 
     decrypt(key, fis2, fos2); 

    } catch (Throwable e) { 
     e.printStackTrace(); 
    } 
} 

然后你的主要方法,简直是:

public static void main(String ...args){ 
    long startTime = System.nanoTime(); 

    // call function 
    doMain(); 

    long endTime = System.nanoTime(); 
    long timeDifference = endTime - startTime; 
} 

一种更好的方式来计算的平均时间是做了几次(这需要纳秒的精度跑单不会很准确)。所以你可以这样做:

public static void main(String ...args){ 
    long startTime = System.nanoTime(); 

    // call function 
    for(int i = 0; i < NUM; ++i) 
     doMain(); 

    long endTime = System.nanoTime(); 
    long timeDifference = endTime - startTime; 
    double avgTime = (double)timeDifference/(double)NUM; 
} 

我会强烈告诫你,虽然这可能不准确。在尝试计时时需要注意两点:1)操作系统是否会假定数据已经在RAM中; 2)体系结构是否假设数据已经在缓存中。如果你运行这么多次,你可能会以读取/写入磁盘的速度以RAM和而不是的速度运行。要真正获得平均速度,您需要确保操作系统必须读取/写入磁盘(这可能需要许多中间“虚拟”读取/写入)。

相关问题