幻影链生成的字节码与Java生成的字节码相比,性能是否相当?

3
从现在开始出现的众多JVM语言中,有一种似乎特别吸引人。请看:http://fantom.org/doc/docIntro/Tour.html。我只是想知道,如果忽略动态类型特性,生成的字节码是否与Java具有相同的性能表现...附:关于性能的说明。
3个回答

6

我进行了一些快速排序的性能测试。

Int[100.000] array quicksort
  Java ~ 11ms
  Java using long and ArrayList<Long> ~ 66ms
  Fantom ~ 97 ms

Int[1.000.000] array quicksort
  Java ~ 91ms
  Java using long and ArrayList<long> ~ 815ms
  Fantom ~ 1100ms.

因此,我认为目前Fantom的代码运行速度比Java的代码慢约10倍。但请注意,我使用的是Java的int和Fantom的Int,它们并不相同。Java的int是32位的,而Fantom的是64位的

经过一些分析,有迹象表明Fantom代码的性能几乎与Java一样好。但是如果性能绝对关键,请避免使用Lists,使用平台特定版本的lists或降级到本机,并编写Java代码。

编辑:我与Brian进行了谈话,他证实了我的怀疑。Fantom较慢的原因是因为所有的Int都是64位整数,而所有的Int[]数组类似于ArrayList<Long>。新的测试显示了差异。Fantom仍然较慢的原因可能是它的Duration、Int和List类具有比普通的ArrayListIntegerSystem.currentMillis更多的方法/字段。这是一个可能适合您的权衡。如果您真的需要高性能,只需创建一个本地方法并在Java/C#/Javascript中编程。这样您将获得与Java相当的性能。

如果您想要自行测试,以下是源代码:

Fantom源代码:

class TestQuickSort
{

   public static Void swap(Int[] a, Int i, Int j) {  
    temp := a[i];  
    a[i] = a[j];  
    a[j] = temp;  
   }  

   public static Void quicksortA(Int[] a, Int L, Int R) {  
    m := a[(L + R) / 2];  
    i := L;  
    j := R;  
    while (i <= j) {  
     while (a[i] < m)  
      i++;  
     while (a[j] > m)  
      j--;  
     if (i <= j) {  
      swap(a, i, j);  
      i++;  
      j--;  
     }  
    }  
    if (L < j)  
     quicksortA(a, L, j);  
    if (R > i)  
     quicksortA(a, i, R);  
   }  

   public static Void quicksort(Int[] a) {  
    quicksortA(a, 0, a.size - 1);  
   }   

  static Void main(Str[] args) {  

    // Sample data  
    a := Int[,]

    for(i := 0; i<1000000; i++)
    {
      a.add(i*3/2+1)
      if(i%3==0) {a[i]=-a[i]}
    }

    t1 := Duration.now 
    quicksort(a);  
    t2 := Duration.now 
    echo((t2-t1).toMillis)  

   }  
}

在所有的int类型和ArrayList中替换为long类型后,Java的性能将得到提升。原始的Java实现可以在http://stronglytypedblog.blogspot.com/2009/07/java-vs-scala-vs-groovy-performance.html找到。

import java.util.ArrayList;
public class QuicksortJava {  

 public static void swap(ArrayList<Long> a, long i, long j) {  
  long temp = a.get((int)i);  
  a.set((int)i, a.get((int)j));  
  a.set((int)j, temp);  
 }  

 public static void quicksort(ArrayList<Long> a, long L, long R) {  
  long m = a.get((int)(L + R) / 2);  
  long i =  L;  
  long j =  R;  
  while (i <= j) {  
   while (a.get((int)i) < m)  
    i++;  
   while (a.get((int)j) > m)  
    j--;  
   if (i <= j) {  
    swap(a, i, j);  
    i++;  
    j--;  
   }  
  }  
  if (L < j)  
   quicksort(a, L, j);  
  if (R > i)  
   quicksort(a, i, R);  
 }  

 public static void quicksort(ArrayList<Long> a) {  
  quicksort(a, 0, a.size() - 1);  
 }  

 public static void main(String[] args) {  

  // Sample data  
  long size = 100000;
  ArrayList<Long> a = new ArrayList<Long>((int)size);  
  for (long i = 0; i < size; i++) {  
   a.add(i * 3 / 2 + 1);  
   if (i % 3 == 0)  
    a.set((int)i, -a.get((int)i));  
  }  

  long t1 = System.currentTimeMillis();  
  quicksort(a);  
  long t2 = System.currentTimeMillis();  
  System.out.println(t2 - t1);  

 }  

}  

2
我认为最终的答案是进行性能分析。Fantom可以输出.jar文件,您可以使用任何Java分析器来检查它。然后,您可以尝试使用native优化关键性能段。大多数情况下,它与使用ArrayList和Long(分别用于数组和整数)的Java具有相同的性能。 - Daniel Fath
我认为目前Fantom的字节码运行速度比Java的字节码慢了大约10倍。这是不正确的。您从单个微基准测试中得出了过于深远的结论,即使考虑到Int <-> Double效应。一个合理的结论是:有一个模糊的暗示,即Fantom几乎和Java一样快,但要注意Int列表,因为它们很慢。 - Lii
没错,但那是在我下面发表评论之前写的。无论如何,问题已经解决了。感谢你指出这个问题。 - Daniel Fath

2

我对fantom没有经验,但看起来fantom解释器可以使用Java、.NET或JS库,但是fantom编译后的字节码不能直接被Java、.NET或JavaScript读取。

话虽如此……我稍后会检查一下,这看起来很有趣 :)


是的,那是真的;然而你可以简单地强制Fantom输出.jar文件而不是.pod(Fantom的.jar类似物)。另外,如果我没记错的话,Fantom有Java FFI,但没有.NET和JS(仍在开发中)。 - Daniel Fath

2

Fantom编译成自己的字节码格式,称为"fcode",然后在运行时将其转换为Java字节码或IL - 更多细节请参见此页面:

http://fantom.org/doc/docLang/Deployment.html

JavaScript的处理方式略有不同 - 在编译时,实际的JavaScript源代码从Fantom源代码中生成(以及Fantom运行时所需的所有元数据)- 产生一个独立的js文件,您可以直接在浏览器中运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接