Article Discussion
CLR Design Choices
Summary: Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about IL instructions, non-virtual methods, unsafe code, value types, and immutables.
15 posts.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: March 10, 2004 4:02 PM by Howard
    Bill
     
    Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
    CLR Design Choices
    February 1, 2004 9:00 PM      
    Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about IL instructions, non-virtual methods, unsafe code, value types, and immutables.

    Read this Artima.com interview with the chief designer of C#:

    http://www.artima.com/intv/choices.html

    What do you think of Ander's comments?
    • John
       
      Posts: 1 / Nickname: johnquine / Registered: February 7, 2004 11:27 PM
      Re: CLR Design Choices
      February 8, 2004 4:33 AM      
      Quoting Anders: "The concept of an immutable object is very useful, but it's just up to the author to say that it's immutable."

      By "say that it's immutable" is Anders referring to stating this in documentation or is there something 'stronger'?
      • Bill
         
        Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
        Re: CLR Design Choices
        February 8, 2004 8:31 AM      
        > Quoting Anders: "The concept of an immutable object is
        > very useful, but it's just up to the author to say that
        > it's immutable."
        >
        > By "say that it's immutable" is Anders referring to
        > stating this in documentation or is there something
        > 'stronger'?

        Nothing stronger. You state the instances of a class are immutable in the class's contract, which is human-language text. This is the same in Java. Anders pointed out that it is hard for a compiler and runtime to guarantee that something is immutable as seen from the outside without also making it fully immutable on the inside, which means it can't enjoy the benefit of having a local cache.
    • Gregg
       
      Posts: 28 / Nickname: greggwon / Registered: April 6, 2003 1:36 PM
      Re: CLR Design Choices
      February 9, 2004 8:26 PM      
      When you look at the design and complexity of the Sun JVM, you can start to understand some potential motivations for some of the differences between Java and C#. There is a lot of technology involved in Sun's implementation. If you had to recreate all of that technology to compete, would you not try and compete with less technology? I think some of the .NET design is based on compromise that they hoped would shorten their time to market.

      I think that the decisions for inheritance that parallel Java are related to the fact that the CLR is something shaped after Java. There are other decisions visible in the architecture of the CLS/CLR as well. JIT-Technologies are much more mature. But, if they had allowed interpretation to be possible, that would have meant that your Microsoft applications were portable to another platform and this could be a 'bad marketing' decision given the history of Microsoft.

      One of the reasons I like Java is because the JIT can make decisions about optimization with much more insight than I could ever express with declarative tokens.

      The inlining of any particular code can happen in lots of places with lots of differing techniques. If you consider the infinite information you have at runtime compared to the limited information you have at compile time, there are a lot of reasons to delay binding until runtime, and to adjust the bindings over time. Anders qualifies his statement appropriately given Bills particular example. His original statement seemed to be that you can't optimize a virtual call unconditionally.

      Regarding unsafe code and JNI... Java, for me, is about simplifying and unifying the programming canvas. If you are always trying to integrate old code with Java, then you might as well just commit yourself to live with the situations that JNI presents. I think that the frustration with JNI is in fact a good indication of just how different the Java and C/C++ programming domains really are.

      Having a unified GC and Threading model in Java trying to interface to the really unsafe environments of C and C++ is where all the complexity really comes from. There are probably some ways to simplify JNIs use. I could imagine a C language parser that would rip through a header file, and create a class (or two) that wrapped all the functionality expressed there into JNI code.

      It seems to me that the CLR is able to integrate unsafe with the .NET languages because it is bound so tight to the OS and thus has insight into the target environment that JNI can't possibly express trivially.
    • Frank
       
      Posts: 11 / Nickname: fmitchell / Registered: January 31, 2003 9:53 AM
      Re: CLR Design Choices
      February 3, 2004 10:13 PM      
      > Anders Hejlsberg: They can never inline a virtual method invocation.

      Well, actually you can, if you can determine that no class currently loaded overrides that method. Of course, as soon as you load a new class you have to recompute all classes containing the inlined method, so you're probably better off with a static call you can simply redefine in one place.

      Still, it might be important enough optimization to warrant the extra overhead. See http://smarteiffel.loria.fr/papers/papers.html#OOPSLA97 for the results of optimizing one application (albeit in Eiffel, not Java).

      If your environment uses some exotic module system that restricts access, you can go ahead and inline. At OOPSLA 2003, some IBM researchers proposed a module system called ModJava, with access restrictions over and above package access; see http://oopsla.acm.org/oopsla2003/files/pap-session-language-design.html for an abstract.
      • Bjarne
         
        Posts: 48 / Nickname: bjarne / Registered: October 17, 2003 3:32 AM
        Re: CLR Design Choices
        February 4, 2004 5:49 PM      
        > Frank Mitchell :
        > > Anders Hejlsberg: They can never inline a virtual method
        > invocation.
        >
        > Well, actually you can, if you can determine that no class
        > currently loaded overrides that method.

        In particular, in C++ it is trivial to inline virtual functions invoked for local or global objects.

        >Of course, as
        > soon as you load a new class you have to recompute all
        > classes containing the inlined method, so you're probably
        > better off with a static call you can simply redefine in
        > one place.
        >
      • Tim
         
        Posts: 10 / Nickname: tpv / Registered: December 9, 2002 1:41 PM
        Re: CLR Design Choices
        February 4, 2004 11:25 PM      
        > > Anders Hejlsberg: They can never inline a virtual method
        > invocation.
        >
        > Well, actually you can, if you can determine that no class
        > currently loaded overrides that method.

        I would appear to me that you only need to know the set of possible concrete classes that could by called by that method invocation.

        e.g.
         new Integer(1).toString() 
        
        could be inlined.

        but, so could
        MyInterface object = arg ? new MyClass() : new MySubClass();
        object.doSomething();
        
        if you know that MySubClass extends MyClass but doesn't override doSomething

        So if you know the complete set of classes that object could be, and they all share an implementation of doSomething, then you can inline it.
        • Bill
           
          Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
          Re: CLR Design Choices
          February 5, 2004 3:02 AM      
          > I would appear to me that you only need to know the set of
          > possible concrete classes that could by called by that
          > method invocation.
          >
          > So if you know the complete set of classes that object
          > could be, and they all share an implementation of
          > doSomething, then you can inline it.

          The trouble is that in dynamic runtimes like Java or .NET, you are usually not certain you know all the types that will ever be loaded. Types that provide new implementations can in general be loaded dynamically later. I assume that's why Anders said you can never inline virtual methods, because sometime later, a new implementation could show up.

          The way that I had heard this inlining is done in adaptive optimizing VMs involved a type check before entering the inlined code, just to make sure it was the expected type. This does cost some time to check the type, but one would imagine far less time than an actual method call.

          But what was most interesting to me about this technique was something I heard Terence Parr describe at a Java users group talk I attended many years ago. He said that in practice in running apps, the vast majority of virtual method invocations turn out to be "monomorphic" or "bimorphic". By monomorphic, he meant only one implementation of a virtual method is ever called. By bimorphic, he meant only two implementations of the virtual method are ever called. He suggested that only a rather small percentage of virtual method invocations turn out to be "megamorphic," where lots of different implementations are called.

          So chances are apparently good that only one or two implementations of a virtual method will ever actually be called as the program runs. In those monomorphic and bimorphic cases, one would imagine that it would be advantageous -- in the parts of the code that are being executed most of the time -- to inline those one or two implementations in use and check the type before plowing ahead.

          And this actually speaks to everyday Java programming practice. Anders had mentioned performance (as well as versioning) concerns when I asked him why non-virtual was the default method access level in C#, and said that Java programmers forget to mark their methods final and that hurts performance. Well, my understanding is that that with modern VMs there isn't much correlation between final marking and performance. You shouldn't be marking methods final in Java just to achieve performance, because it probably won't help.
          • David
             
            Posts: 3 / Nickname: dlramsey / Registered: April 4, 2002 9:57 AM
            Re: CLR Design Choices
            February 5, 2004 1:39 PM      
            This is just an observation but Hejlsberg has said numerous things lately that sound more like marketing statements about Microsoft's chosen products than honest engineering statements. And that puts me on edge as well as questioning everything he says now in terms of whether he's trying to achieve something political as opposed to something technical.
            • Matt
               
              Posts: 62 / Nickname: matt / Registered: February 6, 2002 7:27 AM
              Re: CLR Design Choices
              February 5, 2004 7:08 PM      
              > This is just an observation but Hejlsberg has said
              > numerous things lately that sound more like marketing
              > statements about Microsoft's chosen products than honest
              > engineering statements. And that puts me on edge as well
              > as questioning everything he says now in terms of whether
              > he's trying to achieve something political as opposed to
              > something technical.


              Could you point out some examples of these? I'm not contradicting you, I really think this would be the place to discuss such things.

              By the way, Bill pointed out in a previous thread (may have been in response to a similar comment in a either the previous isntallment of this interview Anders, or the one previous to that...) that almost all the people he interviews are partisans with respect to the technology that they have developed. This is, of course, a natural phenomenon and one to be expected. Guido van Rossum is partial to Python, Yukihiro Matsumoto is partial to Ruby, Bertrand Meyer is partial to Eiffel, Bjarne Stroustrup is partial to C++, James Gosling is partial to Java and so on. These prejudices should come as no surprise, because they are a product of not just the fact that these people created particular systems, but because they created them in the particular way that reflects their judgements and preferences.

              However, if you can point out some evidence of real marketing hype, then let's discuss it here!
          • Todd
             
            Posts: 27 / Nickname: tblanchard / Registered: May 11, 2003 10:11 AM
            Re: CLR Design Choices
            February 25, 2004 9:12 AM      
            Anders had mentioned performance (as well as versioning) concerns when I asked him why non-virtual was the default method access level in C#, and said that Java programmers forget to mark their methods final and that hurts performance. Well, my understanding is that that with modern VMs there isn't much correlation between final marking and performance. You shouldn't be marking methods final in Java just to achieve performance, because it probably won't help.

            Which brings to mind Perlis' quote about low level languages requiring attention to the irrelevant. Object Orientation demands polymorphism. Anything else is unexpected behavior. Being forced to keep track of this is just stupid. Justifying it with performance concerns in the era of GHz processors is even more so.
            • Matt
               
              Posts: 62 / Nickname: matt / Registered: February 6, 2002 7:27 AM
              Re: CLR Design Choices
              February 25, 2004 0:00 PM      
              Good point Todd. Reminds me of wading through C++ code with inordinate usage of inline, and register even in places where they didn't make sense, like having more register variables than your CPU has registers.

              I have found in my use of C#, that this excessive tagging required at the early stages of class development just makes things more brittle. You are (okay, I am) almost never right about all the initial decisions you make about what should and should not be virtual. That just means when writing your derived classes, you find yourself going back to the base class and making things virtual or not posthumously.

              I'm still not convinced the concern over the problem of accidentally overriding previously non-existent methods in the base class is weighty enough to merit a new overload of the meaning of new and the annoyance of having to choose between it and override all the time, either.
      • Frank
         
        Posts: 11 / Nickname: fmitchell / Registered: January 31, 2003 9:53 AM
        Re: CLR Design Choices
        February 3, 2004 10:15 PM      
        Actually, the Eiffel reference should have been http://smarteiffel.loria.fr/papers/papers.html#JMLC97
        • Jakob
           
          Posts: 1 / Nickname: jpraher / Registered: September 18, 2003 7:48 AM
          Re: CLR Design Choices
          March 8, 2004 0:24 AM      
          I have created a project implementing modjava.
          I have a very minimal ref impl in the cvs. I am currently in the design process of crafting a better spec for implementing a new version.

          For instance the uuid thing is a bad idea, since it creates a dichotomy of identification, since no user will use/know the uuid of a module.

          Also the spec lacks of versioning.
          It is a complex task doing a module system right. If you do a bad task, you can do more harm than good. In some essence I can understand that there is nothing compelling for java, because of the complexity. - Simply copying the assembly design wont help either.

          If you want to add your comments to the design, I have a wiki, accessible through: http://modjava.sourceforge.net
    • Steven
       
      Posts: 1 / Nickname: strobert / Registered: February 10, 2004 7:29 PM
      Re: CLR Design Choices
      February 11, 2004 0:39 AM      
      About the only thing in the series that really had me in disagreement with Anders was his remarks about 'const'.

      Assuming you have properly coded API's (and if you don't you should be wrapping them so that all of your (companies) code is using a good interface, then things that should be const are const and vice-versa.

      The whole point of const (at least in a function arg) is it is a commitment/contract/whatever you want to call it that the function won't modify the object you give it. If I have a const object (say I am in a const method or got a const object passed in to me -- which boil down to the same thing since in the first case this is const) and I want to call a method that takes a non-const version, then it is a good thing I can't. Well at least can't without casting it away which is something that should get flagged by any decent code reviewer.

      If you did "cast away" const then you are violating the agreement with whomever called you that you wouldn't modify the const object.

      Back in my main C++ days (most of my programming these days is in perl doing network admin automation and internal tools since my company went Java and I can't stand java :)) we used const quite effectively to provide a good semantic communication to people writing code.
      • Howard
         
        Posts: 25 / Nickname: hlovatt / Registered: March 3, 2003 1:20 PM
        Re: CLR Design Choices
        March 10, 2004 4:02 PM      
        Steven Roberts said:

        > About the only thing in the series that really had me in
        > disagreement with Anders was his remarks about 'const'.
        >
        > [Stuff deleted]
        >
        > Back in my main C++ days (most of my programming these
        > days is in perl doing network admin automation and
        > internal tools since my company went Java and I can't
        > stand java :)) we used const quite effectively to provide
        > a good semantic communication to people writing code.

        The standard method in Java is to define a class with a constant interface, get methods and **no** set methods, then to derive a class from it with the set methods. This behaves just like const in C++.

        The problem, as in C++, is that the above const/mutable classes can't be compiler enforced, only enforced at runtime. IE you can cast away const delibrately or accidently! A further issue is that you often need to repeat methods, e.g. a max method that returns a const for consts and a max method that returns a mutable for mutables. I think this is what Anders Hejlsberg was getting at and is the big difference between final in Java and const in C++.

        A better method is immutable, see:

        http://developer.java.sun.com/developer/bugParade/bugs/4617197.html

        A compiler that enforces immutables as described in the above RFE and available under the LGPL is:

        https://pec.dev.java.net/