论坛首页 编程语言技术论坛

IKVM 编程武林之.NET派的北冥神功

浏览 28006 次
该帖已经被评为良好帖
作者 正文
   发表时间:2009-12-29  
ray_linn 写道

这里我想到如果实现动态ngen--似乎更美妙,只ngen到被调用的那些方法,可以称为动态ngen或者静态hotspot

动态ngen?和jit有什么区别?除非把native code保存到磁盘上,那倒算是有区别,不过那样似乎就把ngen和jit的缺点都占了——既不能动态优化,又必须在运行时编译。
0 请登录后投票
   发表时间:2009-12-29  
幸存者 写道
ray_linn 写道

这里我想到如果实现动态ngen--似乎更美妙,只ngen到被调用的那些方法,可以称为动态ngen或者静态hotspot

动态ngen?和jit有什么区别?除非把native code保存到磁盘上,那倒算是有区别,不过那样似乎就把ngen和jit的缺点都占了——既不能动态优化,又必须在运行时编译。


我的意思是对于GAC里的类,替换被调用的IL为native code,这样之后的所有调用都是native code,而未被调用的IL则继续保持原来的格式。
0 请登录后投票
   发表时间:2009-12-29  
JPython已经不叫JPython很久了……现在是Jython。该计划一直半死不活,到去年才开始重获生机开始快速发展。看看SourceForge中间有些版本是断的……
IronPython是从2.0开始转用DLR的(或者说把DLR剥离出来的)。剥离出来的DLR原本就是IronPython 1.x的一部分,独立出来之后为什么性能会降低……?随着经验的积累,在DLR的tuning也比IronPython 1.x的时代要好了。IronPython 2.6的性能比IronPython 2.0的性能……well有些地方因为实现的功能更复杂了所以……那不是DLR的错嗯。至少IronPython 2.6的启动速度比2.0快多了,在DLR的解释器的协助下。

DLR里的很多优化技巧也跟源于Smalltalk/Self系的技术,跟HotSpot的有相似的源头;像是callsite caching、hidden class等……用起来也很方便。
0 请登录后投票
   发表时间:2009-12-29  
ray_linn 写道
幸存者 写道
ray_linn 写道

这里我想到如果实现动态ngen--似乎更美妙,只ngen到被调用的那些方法,可以称为动态ngen或者静态hotspot

动态ngen?和jit有什么区别?除非把native code保存到磁盘上,那倒算是有区别,不过那样似乎就把ngen和jit的缺点都占了——既不能动态优化,又必须在运行时编译。


我的意思是对于GAC里的类,替换被调用的IL为native code,这样之后的所有调用都是native code,而未被调用的IL则继续保持原来的格式。

谈到这个话题不得不提JTL式的编译器……just-too-late 
0 请登录后投票
   发表时间:2009-12-29   最后修改:2009-12-29
RednaxelaFX 写道
JVM的性能进步对上层应用的影响不可谓不大。其中一个有趣的侧面是Sun的javac:从JDK 1.3开始它就会忽略-o编译开关——Sun认为在Java源码到JVM字节码过程中的优化没多少必要,反正HotSpot能提供足够优化。虽说这个设计到底是不是真的合理还可以商榷……

JVM的实现自然也会影响到库的实现。之前正好记过一篇关于反射调用方法的一个log,也算是能扯上关系。

还是你对VM相关的技术更了解,我只是知道,拍脑袋认为的一些个人观点而已。

我没有什么证据,随口说一些功能上的例子吧,例如很好用的java.util.concurrent.atomic.AtomicInteger类,底层使用了不开源的sun.misc.Unsafe(未必不开源,实际上是我没花时间找,默认的JDK中貌似没有这个类的源代码),如果对应到CLR中不知能否正确实现AtomicInteger类的功能。

还有像在多核CPU下transient关键字在JVM自己的不同版本中实现都不一样,不知道CLR会如何处理。
0 请登录后投票
   发表时间:2009-12-30   最后修改:2009-12-30
icewubin 写道
RednaxelaFX 写道
JVM的性能进步对上层应用的影响不可谓不大。其中一个有趣的侧面是Sun的javac:从JDK 1.3开始它就会忽略-o编译开关——Sun认为在Java源码到JVM字节码过程中的优化没多少必要,反正HotSpot能提供足够优化。虽说这个设计到底是不是真的合理还可以商榷……

JVM的实现自然也会影响到库的实现。之前正好记过一篇关于反射调用方法的一个log,也算是能扯上关系。

还是你对VM相关的技术更了解,我只是知道,拍脑袋认为的一些个人观点而已。

我没有什么证据,随口说一些功能上的例子吧,例如很好用的java.util.concurrent.atomic.AtomicInteger类,底层使用了不开源的sun.misc.Unsafe(未必不开源,实际上是我没花时间找,默认的JDK中貌似没有这个类的源代码),如果对应到CLR中不知能否正确实现AtomicInteger类的功能。

还有像在多核CPU下transient关键字在JVM自己的不同版本中实现都不一样,不知道CLR会如何处理。




System.Threading.Interlocked.CompareExchange() = sun.misc.Unsafe.compareAndSwapInt().

AtomicInteger.incrementAndGet()=Interlocked.Increment(ref foo);

通过C#的等价替代,很自然就实现java基础类库的CLR版,(由于IKVM根本不依赖于JDK,所以必须提供自己的CLR版java类库以便让自己的java应用引用)
0 请登录后投票
   发表时间:2009-12-30   最后修改:2009-12-30
icewubin 写道
我没有什么证据,随口说一些功能上的例子吧,例如很好用的java.util.concurrent.atomic.AtomicInteger类,底层使用了不开源的sun.misc.Unsafe(未必不开源,实际上是我没花时间找,默认的JDK中貌似没有这个类的源代码),如果对应到CLR中不知能否正确实现AtomicInteger类的功能。

基本上整个JDK都开源了,像Unsafe这么重要的类型要是不开源那也未免太不厚道了 XD

以java.util.concurrent.atomic.AtomicInteger举例:
AtomicInteger.compareAndSet()的实现如下:
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

该实现依赖于sun.misc.Unsafe。在class文件被加载时,sun.misc.Unsafe.compareAndSwapInt()就被识别为intrinsic方法了。
vmSymbols.hpp
do_intrinsic(_compareAndSwapInt,        sun_misc_Unsafe,        compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \
do_name(     compareAndSwapInt_name,                          "compareAndSwapInt")                                   \
do_signature(compareAndSwapInt_signature,                     "(Ljava/lang/Object;JII)Z")                            \


在解释模式下,Unsafe.compareAndSwapInt()被实现为:
unsafe.cpp
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

通用的Atomic::cmpxchg()实现为:
atomic.cpp
unsigned Atomic::cmpxchg(unsigned int exchange_value,
                         volatile unsigned int* dest, unsigned int compare_value) {
  assert(sizeof(unsigned int) == sizeof(jint), "more work to do");
  return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest,
                                       (jint)compare_value);
}

在Windows/x86(非AMD64)上的实现为:
inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

本来是可以直接用Win32 API中的InterlockedCompareExchange(),不过Sun的工程师觉得这个函数在Win95上跑不了所以就干脆自己写汇编了。
这里的重点就是x86的cmpxchg指令。这是一种compare-and-swap(CAS)系的指令。

在编译模式下,JIT会识别出对Unsafe.compareAndSwapInt()的调用。其中-client编译器(也称为C1)在x86上会通过下面一系列调用最终生成cmpxchg指令:
c1_LIRGenerator_x86.cpp
else if (type == intType)
  __ cas_int(addr, cmp.result(), val.result(), ill, ill);

c1_LIR.cpp
append(new LIR_OpCompareAndSwap(lir_cas_int, addr, cmp_value, new_value, t1, t2));

c1_LIRAssembler_x86.cpp
else if (op->code() == lir_cas_int) {
  __ cmpxchgl(newval, Address(addr, 0));
}

assembler_x86.cpp
// The 32-bit cmpxchg compares the value at adr with the contents of rax,
// and stores reg into adr if so; otherwise, the value at adr is loaded into rax,.
// The ZF is set if the compared values were equal, and cleared otherwise.
void Assembler::cmpxchgl(Register reg, Address adr) { // cmpxchg
  if (Atomics & 2) {
     // caveat: no instructionmark, so this isn't relocatable.
     // Emit a synthetic, non-atomic, CAS equivalent.
     // Beware.  The synthetic form sets all ICCs, not just ZF.
     // cmpxchg r,[m] is equivalent to rax, = CAS (m, rax, r)
     cmpl(rax, adr);
     movl(rax, adr);
     if (reg != rax) {
        Label L ;
        jcc(Assembler::notEqual, L);
        movl(adr, reg);
        bind(L);
     }
  } else {
     InstructionMark im(this);
     prefix(adr, reg);
     emit_byte(0x0F);
     emit_byte(0xB1);
     emit_operand(reg, adr);
  }
}

在else分支中,生成的0x0F 0xB1就是cmpxchg

在.NET上,对应的功能由System.Threading.Interlocked提供。Unsafe.compareAndSwapInt()对应的是System.Threading.Interlocked.CompareExchange()。底下依赖的x86指令也同样是cmpxchg。
Interlocked类在.NET 1.0的时候就已经有了,而AtomicInteger是Java 5新增的,这个嘛……
0 请登录后投票
   发表时间:2010-01-05  
高手很多啊。

mono和ikvm有多大的实际意义?
0 请登录后投票
   发表时间:2010-01-05  
liudun 写道
mono和ikvm有多大的实际意义?

要是用广告词语气的话,我会说实际意义在于“leverage”,在不同的场景下延用已掌握的技术/技巧。例如说:
·熟悉.NET开发的人希望开发Linux、Mac等平台上的程序 -- Mono/Portable .NET
·熟悉.NET开发的人希望开发iPhone、Wii、PS3等平台上的程序 -- Mono
·熟悉.NET的人希望利用Java的优秀的服务器 -- Grasshopper (看这里的评论
·熟悉.NET技术但希望降低软件成本,希望在Linux上部署ASP.NET应用 -- Mono
·熟悉Java的人希望迁移到.NET平台上 -- IKVM/Ja.NET
·.NET程序员希望以很小的成本使用Java已有的丰富的库 -- 同上
  不止一次见到有人拿JRubyRhino之类的Java实现的脚本引擎用IKVM放到.NET上跑了……人家就是有这乐子
·希望在程序中嵌入高级语言运行环境作为脚本或高级开发语言 -- Mono (看Second Life或者Unity
  Mono虽然比不上一些主流的JVM先进,但它的执行速度好歹还是比CPython和CRuby这些脚本引擎快多了,自带的库也很丰富(同时也可根据需要裁剪),甚至有对SIMD、continuation等的支持
·希望在资源极度受限的环境中用类型安全的语言、在托管环境中开发 -- Portable.NET (看这里提到的几个实例)
·Linux开发者希望借用.NET的理念在Linux上做开发 -- Mono
  这是Miguel创始Mono计划的初衷,为了在Linux上能更方便的开发桌面应用之类的;他觉得C做这种事情太麻烦了。
  好吧现在的话用Vala也可以……
·自由软件世界的同志不愿意看到微软树立了行业标准(CLI、C#)而大摇大摆 -- Portable .NET

随便举了些场景的例子。大家都有自己的算盘,有自己的需求;如果某东西的成熟度正好能满足场景与需求,那就拿来用呗 >_<b
0 请登录后投票
   发表时间:2010-01-05  
Linux下开发桌面应用,QT是不是更适合?
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics