解决方案 »

  1.   

    还有就是matlab程序本身并没有因为调用多而耗时, 不管是开始还是后面每次执行耗时都差不多(在matlab程序里加入时间统计测试出的结果)。  所以问题也就是jni频繁调用相关的东西吧,但我并不确定, 也不知道如何解决。 
      

  2.   

    测试打印的结果:第1w用时:4
    第2w用时:7
    第3w用时:22
    =====
    第1w用时:41
    第2w用时:51
    第3w用时:61
      

  3.   

    你有没有考虑System.currentTimeMillis(); 所花费的时间,你打出来的时间是JNI的执行时间还是java方法和JNI一起执行的时间?
    你是线程睡眠后再执行的第二个方法,你拆开执行看看所耗时间。
      

  4.   

     Object[] calResult = myCal.myCal(4, 2, 3);这个是多线程还是单线程?有无线程安全问题?有无同步问题?
      

  5.   

    就这么多代码,另外有两个jar, 给你也测试不了, 必需装matlab环境才能跑。
      

  6.   


    我现在初步确定了问题在返回值这块,   Object[] calResult = myCal.myCal(4, 2, 3);  这个第一个参数是一个int 表示获几个返回值, 可以比matlab 函数返回值个数小, 同时也是calResult 数组的长度。  当我不获取返回值也就是Object[] calResult = myCal.myCal(0, 2, 3);  测试打印的时间稳定在2秒, 比较短且不会增长
      

  7.   


    Object[] calResult = myCal.myCal(4, 2, 3);
    前后打印耗时时间看下效果
      

  8.   

    有没有做1W次之后dump一下内存看看呢?jstat看一下内存的使用情况 呢?我觉得JNI调用再多次也不会这样子,多数是什么地方有memory leak或者是线程未释放之类的问题导致的。
      

  9.   


    这个打印下结果是一次调用可能消耗0、16、32 毫秒。  且越往后出现16、32的次数越多。 
    也就是1w次会多出10多秒的样子, 再往里面就没法看了, 反编译出matlab的jar没有注释, 蛮复杂的,点到最里面就是native方法
      

  10.   


    怎么dump,具体要怎么操作呢?  我只是用jconsole看到jvm 内存正常
      

  11.   


    怎么dump,具体要怎么操作呢?  我只是用jconsole看到jvm 内存正常用jmap之类的看看你跑这么多次,内存没有增长 么?
      

  12.   

    先使用System.currentTimeMillis(); 打印看下是哪步耗时吧
      

  13.   

    你这一堆static,问题出在大作用域的MyCal里。建议你查看MyCal里的代码,是否存在未释放的资源啥的,或者在重复执行时影响执行效率的东东
      

  14.   

    把静态去掉 换成new的方式试试
      

  15.   

    JVM 与本机代码之间的通信通常很慢,因此,太多的 JNI 调用可能会降低性能
      

  16.   

    我在MT4中调用过matlab生成的DLL,调用速度的问题倒是没怎么留意,
    调用matlab只是为了验证matlab里提供的东西能不能解决我的问题,
    后来发现可以解决,就把matlab里的东西用JAVAl来实现,
    里面的东西大多有其他语言的替代实现,LZ可以找找
      

  17.   

    正确调用的代码是这样的:在使用完计算结果 Object[] calResult; 后加入 MWArray.disposeArray(calResult); 这么一句话。就是for (Object o : calResult) {
             MWNumericArray m = (MWNumericArray) o;
             m.dispose();
             }通过debug发现 calResult 实际类型是MWNumericArray, 这个是matlab转为java后的一种数据类型(矩阵、向量、数值),  里面的一个NativeArray 很明显就是matlba 的数据(byte[])。 NativeArray 的 finalize方法被重写调用dispose()。 上面m.dispose(); 也就是调用内部NativeArray 的dispose()。看到这里大家获取有些疑惑, 因为finalize方法被垃圾回去的时候会自动被调用,也就是说calResult 出了作用域以后即会被调用dispose方法, 我们无需加入上面的代码。 我也真实因为这个观点才犯错的。
    这里有篇文章对于finalize可能引发内存溢出 http://ju.outofmemory.cn/entry/74671在例子(生产的例子不是测试例子)中并不会内存溢出(jvm设置的内存比较大), 但问题确实是Finalizer线程比主线程优先级低,当这么大的一直循环创建了大量Finalizer对象, 却没能被调用执行。 这个我通过jmap弄出dump文件后证实确实如此, 在测试内存快慢的的时候几乎全被Finalizer对象占有。手动调用dispose后正确解决了这个问题。想起之前看到Java编程思想还是jvm那本书里说 java程序员应该完全忘记finalize方法。在国外网上查到所有调用matlab的例子中都会像上面显示调用dispose, 然后带句注释
    //clean up the resources used by the generated MATLAB code.  获取
    //free native resources 
    并没说dispose最终做了什么, 反编译出的代码里面是native调用。 我猜测是java调用Matlab使用了Direct Memory
    然后我通过-XX:MaxDirectMemorySize=1M测试无变化,应该也不是Direct Memory被大量占用的问题。目前就知道这些东西, 问题已经解决, 但我还是不知道Java调用matlab机制是什么, dispose的native方法到底做了什么。
      

  18.   

    其实就是这个测试产生的垃圾内存,JVM根本来不及收集的意思?
      

  19.   

    不是jvm内存
    可能我没说清楚,  慢的问题解决了,但原因还不知道。上面只是说 finalize方法的一些东西。  大量的Finalizer并不是慢的原因。
      

  20.   

    不是jvm内存
    可能我没说清楚,  慢的问题解决了,但原因还不知道。上面只是说 finalize方法的一些东西。  大量的Finalizer并不是慢的原因。
    其实,我一直很好奇你原来的代码中 gc的情况到底 是如何的。照这个文章的说法,应该分析蛮透的了啊。finalize的时候还要通过JNI去调用,而那个文章说一旦finalize有内容的话,又会直接到FGC上面去。这样,FGC相关的参数就会对性能影响很大了。
      

  21.   

    不是jvm内存
    可能我没说清楚,  慢的问题解决了,但原因还不知道。上面只是说 finalize方法的一些东西。  大量的Finalizer并不是慢的原因。
    其实,我一直很好奇你原来的代码中 gc的情况到底 是如何的。照这个文章的说法,应该分析蛮透的了啊。finalize的时候还要通过JNI去调用,而那个文章说一旦finalize有内容的话,又会直接到FGC上面去。这样,FGC相关的参数就会对性能影响很大了。频繁full gc肯定是不行的, 测试是也确实如此,应为不管新生代还是老生代都是一会就满了(我设的值小),全被Finalizer占了没办法只能full gc,并不是因为finalize。  matlab的工具包作者有意或者好心重写了finalize方法, 在里面做了开发人员应该手动调用的
    dispose。  但这个好心并不能完全奏效,原因就是那篇文章说的, 出现这种情况是因为太频繁创建重写了finalize的对象,Finalizer线程跟不上了。对于我生产中也确实产生了大量的Finalizer, 但这对于我服务器jvm配置还是小菜一碟, 我但是测试跑了几乎一个下午jvm老生代也没满呢。  问题就是dispose 里面的jni调用必需手动及时的做。 它里面是清理的matlab的一些东西。
      

  22.   

    那会不会是dispose产生了一个无法多线程工作现象呢?