【问题标题】:How to test the speed of an interactive java code?如何测试交互式java代码的速度?
【发布时间】:2019-05-17 07:52:03
【问题描述】:

我的问题中的重要词是 interactive:对于编程竞赛(UVa 在线评委),我正在编写交互式 java 代码:它在 System.out 上输出并等待 System.out 上的响应。在。

我想测试这段代码的速度,但如果我手动进行交互,我的人工打字技能会减慢执行速度,并且测量会有偏差。

因此,我想要一个线程/app/script/whatever,当我的应用程序在 System.out 上写入时看到,(这个线程/app/script/whatever)然后写入我的应用程序使用它的 System.in 读取的东西.

我的应用程序应该使用 System.in 和 System.out 进行通信,因为一旦我将它提交给在线评委,它就会被评判。

我认为多线程无法完成这项工作,因为 System.in 总是从键盘读取,而不是从另一个线程读取。

import java.util.Scanner;

public class Main {

    public static void main(final String[] args) {
        System.out.println("What now?");
        final Scanner scanner = new Scanner(System.in);
        final String response = scanner.nextLine();
        scanner.close();
        System.out.println("Finished: " + response);
    }
}

如何在没有人在键盘上输入的情况下运行此代码?

【问题讨论】:

  • 这段代码的速度基本无关。时间以JVM启动时间为准。
  • 我要测试的不是这段代码。这是一个示例,以便您了解我想要做什么。我的代码更长,并且有多个 System.in 调用。
  • 如果您使用的是 linux。你可以使用这个命令来检查花费的时间:time java MyClass < put_input_in_this_file.txt
  • 另外,如果你想测试代码的性能,你只需要测量相关的业务逻辑。从上到下衡量一切是没有意义的。尤其是在需要用户输入的情况下,因为理论上这可能需要无限时间。
  • @Saket Santosh Patel 可能会这样做。我只是不确定它是否会起作用,因为使用您的方法,我无法决定何时从put_input_in_this_file.txt 读取每一行。我今晚看看它是否有效。

标签: java performance testing interactive


【解决方案1】:

您的用例肯定可以使用多线程。 Java 机器人框架提供了发送击键的机制。参考:this post

【讨论】:

    【解决方案2】:

    您可以使用处理该问题的自定义InputStream 实现通过另一个线程发送输入。我下面的版本也允许用户输入。

    请注意这个解决方案并不完美,但应该会给您一个大致的印象。

    public static void main(final String[] args) {
        System.out.println("What now?");
        DoubleSourceInputStream inputStream = new DoubleSourceInputStream();
        final Scanner scanner = new Scanner(inputStream);
        new Thread() {
    
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    inputStream.addBytes(("do task " + i + "\r\n").getBytes());
                }
                // to signal we are done, otherwise the queue would be polled forever
                inputStream.addBytes(new byte[] { -1 });
            }
        }.start();
        final String response = scanner.nextLine();
        scanner.close();
        System.out.println("Finished: " + response);
    }
    
    static class DoubleSourceInputStream extends InputStream {
    
        BlockingQueue<Byte> buffer = new LinkedBlockingQueue<>();
    
        @Override
        public int read() throws IOException {
            if (System.in.available() > 0)
                return System.in.read();
            try {
                return buffer.take().intValue();
            }
            catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    
        public void addBytes(byte[] bytes) {
            for (byte b : bytes) {
                buffer.offer(Byte.valueOf(b));
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      使用 Main 类作为引导方法,并在单独的类中实现正在测试的代码,该类对 InputStream(输入)和 PrintStream(输出)进行操作。

      import java.util.Scanner;
      
      public class Main {
          public static void main(final String[] args) {
              MyCode code = new MyCode(System.in, System.out);
              code.run();
          }
      }
      

      现在,在为 MyCode 编写测试时,您不再局限于 System.inSystem.out。从测试中引导代码时,只需将 System.in 和 out 替换为测试代码写入和读取的普通流即可。

      【讨论】:

        【解决方案4】:

        与其重新发明轮子,不如使用终端的功能来完成。

        您正在使用java -jar program.jar 正常运行程序的图像,您现在需要以java -jar program.jar &lt;input.txt 运行它,其中input.txt 包含您在交互运行时通常从键盘传递的所有数据。

        这仅在您的程序是可预测的情况下才有效,但来自不可预测程序的计时结果通常是无用的,除非运行数千次。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-07
          • 2015-10-08
          • 2015-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-22
          相关资源
          最近更新 更多