• Runtime.exec使用错误导致延迟.md


    这篇文章是纪录了一个bug解决的过程,可是我还是没有可以真正地找出bug的缘由。希望大牛可以详解。

    问题的发现

    当接触的系统越来越大的时候,对于系统的性能越来越高的时候,找到表面问题的真正原因就慢慢地成为了一个比較麻烦的问题。说实话,一開始我一直不知道是由于Runtime.getRuntime().exec()导致服务处理时间缓慢。发现这个原因倒是花了不少时间。

    为了方便,我直接就用java调用python脚本。用python脚本处理做核心的机器学习算法的东西。

    而java调用python脚本,我直接就採用了Runtime.getRuntime().exec(),这个方式相似于直接使用了shell来运行。一開始使用的挺好,也没有注意一些细节的问题,慢慢地用着用着,发现有一台机器处理同样地人脸头像比另外一台慢。从经验上考虑过非常多的可能情况,可是都不是问题的真正原因。

    但每个误判。我感觉都非常值得反思。

    网络问题

    由于我使用了内网穿透工具,本身对工具性能也不熟悉。刚開始的时候立马就想到了是不是由于使用了内网穿透工具。导致网速太慢了。由于这个问题我差点儿就无法解决,所以我一想到这个原因,就没有再去想办法攻克了。

    后面直接发现直接从訪问的结果仍然是一样的慢。事实上这个地方我应该去验证一下,直接从内网訪问,看一下速度。

    这样就行避免误判带来的问题了。

    机器配置问题

    由于两台机器配置的时候还是存在一点点不同,我后面又想是不是一台机器配置出现故障?检查了半天还是不能确认是不是机器配置不同,安装的内容不同导致出现了问题。由于没什么时间,干脆我又扔一边去了。

    某些随机因素

    由于一台机器运行高速,另外一台运行缓慢,而出现这样的诡异的问题,非常easy就让人想到是不是代码库由于某些原因,导致了这样的情况。而往往这样的问题就基本是没有办法搞定了。事实上我还是一个新手的时候。我总是怀疑某些问题是由于一些系统错误,随机因素导致的。可是结果往往是自己的错误。由于有了之前的经验,我潜意识就感觉可能是自己哪段代码出现了错误。

    之后通过对代码片段打印时间,每一段运行完都打印时间点。最后查看日志发现,就是在调用process.waitfor的时候,python程序已经返回了,可是java程序仍然没有不论什么响应。还是在wait。

    这样才发现了这个问题。

    然后通过在网上搜索Runtime.getRuntime()运行程序应该注意的事项,找到问题的关键。我使用waitfor,之后再去读取python程序的输出,可是由于输出一直没有被读取。缓冲区满了,程序就被堵塞。

    getRuntime().exec

    getRuntime().exec会返回一个Process。在jdk文档中有说明,Process的缓冲区是有限的,假设输出的内容太多,程序就会被堵塞掉。
    我一開始的程序是像以下这样的:

    ​    ​try {          
    ​    ​         final Process p = Runtime.getRuntime().exec("python test.py");
    ​    ​    ​    ​ p.waitFor();       
    ​    ​         BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    ​    ​         try {
    ​    ​                      while (br.readLine() != null)
    ​    ​                          ;
    ​    ​                      br.close();
    ​    ​          } catch (IOException e) {
    ​    ​               e.printStackTrace();
    ​    ​          }
    ​    ​} catch (Exception e) {
    ​    ​          e.printStackTrace();      
    ​    ​}
    

    这样的结果就是一台机器在waitFor那里被卡住非常长一段时间。然后參考了网上给的原因,将程序改成以下这样:

        try {          
                 final Process p = Runtime.getRuntime().exec("python test.py");
    
                 BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                 try {
                              while (br.readLine() != null)
                                  ;
                              br.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
                  p.waitFor();  
        } catch (Exception e) {
                  e.printStackTrace();      
        }
    

    这样程序就不会长时间卡在那里。甚至于去掉p。

    waitFor程序也是OK的。由于程序结束后,Stream就被close掉了。网上非常多人是遇到了由于exec运行的程序出现了错误,结果Error信息占满了缓冲区,导致程序被挂起。

    原因探究

    从网上看的那些信息仅仅能让我推測可能是由于信息打印太多。没有及时读出,导致程序卡住。

    可是我心里还是有疑问,为什么一台机器ok。另外一台机器会卡住,过非常长时间才返回呢?这里面详细的细节方面的原因我认为我还是没有找对。事实上我python程序打印的东西也不多的。

    另外也有一个可能是python程序运行完后,非常长时间都没有全然返回。

    这也是一个推測的原因。

    尽管我依照网上的方式临时攻克了问题。但这些原因事实上我认为都不够充分。希望有人可以给出正确的解释。基础真的要牢靠。

  • 相关阅读:
    django-3-模板变量,过滤器,静态文件的引用
    django-2-路由配置及渲染方式
    用pycharm运行django项目
    django-1-框架介绍
    django-6-数据库配置及模型创建,激活(django模型系统1)
    用Sklearn实现聚类算法并用散点图展现效果
    方差、标准差、协方差、协方差相关系数
    ARIMa--时间序列模型
    人工智能--第二天--KNN算法实现
    人工智能--第二天--KNN算法
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5232655.html
Copyright © 2020-2023  润新知