Many garbage collectors are only triggered whenever you allocate an object. This means you can just allocate lots of objects as part of your start-up routine, and then as long as you don't create any more objects, you'll get absolutely no gc pauses.
The only negative things I would say about garbage collected languages is that very few implementations give you different gc strategies to choose from and many garbage collected languages make it difficult to know when allocation is occuring. (For example, most Scheme implementations will create garbage when you add two floating-point numbers.) This is more of the problem with the languages and their various implementations and rather than with the concept of garbage collectors.
The beauty of plugging in new collectors would be that one option for a "garbage collector" could really just be malloc (and free of course) to make the system more suitable for certain uses.
All chips are designed to run "at the edge" of the frequency upper limit and so AMD doesn't have an inherent advantage because they do more work per clock cycle and Intel does less work per cycle but has a higher frequency. All chip-makers hit the same physical limitations at about the same time and neither has the advantage because they run at a higher or lower frequency today.
The primary determination of clock-speed (besides process technology of course) is the largest number of transistors and the length of the wires in the critical path of each pipeline stage. For a chip with a higher clock-speed using the same process technology, this means that it has less wire or transistors in the longest path of each stage so it can be clocked faster. The presumption is that this is achieved by having more stages or better logic when compared to some other design, etc. but it really doesn't matter as far as the physics are concerned. All chips max out when the frequency is so high that the signals flowing through the circuits don't have enough time to go from one stage to the next and from this perspective, the only thing that matters is how much wire and how many transistors. If AMD was able to make faster chips, they would. Likewise with Intel.
It all boils down to this: if I have path with 10 units of delay and you have all paths with 8 or less units of delay, you will achieve a higher clock-speed if we use the same manufacturing process. Niether design is better for getting sped-up when moving to the next process technology since they use the same transistors and wire and are running at the same edge "node" in the current process technology.
Where AMD *may* have an advantage is that the top speed of chips may start to be effected by the power-consumption since if the chips get too hot, they will melt. Power-consumption for CMOS is determined by the dynamic component (when CMOS gates change their state they burn power) and a static component (determined by the total number of transistors). You used to be able to ignore the static component but as the feature size decreases, the leakage current begins to become quite noticeable. [AMD is using SOI already to help with this problem. Intel is eventually going to introduce its SOI work-alike (the name escapes me because it was invented by a marketing person).] Most advanced chips designs include circuits which burn power all of the time, but I'll assume that both Intel and AMD use the same tricks with the same small percentage of their transistors (and it is the same transistors with a high dynamic power usage anyways since they are important circuits).
If is conceivable that one design, Intels P4 or AMD64, is "more efficient" in this it uses less power both statically and dynamically, to acheive the same computations. At the end of the day, the more efficient processor may be able to compute the result quicker because it won't have to turn itself off just to cool down compared to the less efficient design. Currently this kind of limitation is only present in very small laptops.
However, you can't automatically assume that low frequency means the AMD64 design is more efficient. It may do more wasted work (speculation) per cycle in trying to do more work per cycle. It might have more transistors in its ALUs burning power, etc. One things that hurts Intel is that because they have a longer pipe-line, they have a higher penalty for branch mispredications, but they may just be able to tweak the branch predictor or make it larger to recoup this deficit.
At the end of the day, you'd probably find out that the two chips are about as efficient as each other (and that PowerPC processors are a little bit more efficient since they have much simpler decoders). I know that both AMD chips and Intel chips both burn a lot of power. If AMD sticks with SOI and Intel uses inferior technology, then AMD will win. But Intel has a lot of money and they probably won't get out-classed in technology by anyone.
I agree that if one were to design a language today, they should be able to use real world experience to take the best features from all of the available languages and make a super-language.
I just want to make sure that you aren't saying that language evolution has uniformaly progressed from ok --> good --> better. Some old languages like Lisp were actually pretty advanced but languages that came after them usually didn't borrow the most powerful ideas since that would have made them slower (either that, or the people making those languages don't share my tastes). Examples of powerful features from Lisp/Scheme: generic arithmetic with arbitrary percision integers, closures, powerful macro systems, dynamic evaluation, and first class continuations
Until recently, performance has always been the most important factor but the tide has turned and people consider safety and ease of use to be the important properties of the language. For example, making (basically) every object a hashtable like Python, Ruby, and JavaScript do is really convenient for quickly making programs with fewer declarations or for adding your own properties to objects you get from someone else code, but people avoided dreaming about such a luxury when trying to create a compiler for a 4MHz 8086 machine. Ease of use was secondary to the degree that C compilers of the day had ints that were only 16 bits by default.
Your certainly bring up some good points especially with your hack for doing inheritance. It isn't quite the same thing as true inheritance though because I'll still have to do tons of casts everywhere and thus the compiler essentialy won't do type-checking the way it would if it understood inheritance. If I use your trick with a manually constructed safe cast which I could probably make using the typeof, then I could probably get what I want which is as much static type checking as possible.
My primary problem with C++ is that while it has almost all of the extra features I think are truly important, it also has tons of "features" which I find confusing, useless, and or dangerous. Whenever I have seen large C++ programs, I invariably wish that they were written in Java or C#.
I agree with you that if a subset of C++ is used wisely, then it is in fact a great language (though I still want to get rid of header files as priority number 1). In fact, using C++ with the CLR even makes C++ better. However, if you worked with some of the "programmers" I work with, you would spend all of your time worrying about the messes you would have to endure when they bumbled around with the complicated semantics of C++. I think this is why Java and C# or so popular even though when C++ is used in the right way, it is more or less as good as Java and C#. (I think C++ would also be more popular today if it went through less churn when it was being standardized so that the various compilers were more compatible in the early days.)
C is a pretty decent language to program in (in some ways better than Java --for example it has function pointers), however it has a few substantial short-comings:
0) Header files suck. ".o" files should contain everything needed to get all of the types and function prototypes needed while compiling. The compiler should be smart enough to compile multiple files at he same time to deal with the forward references problem.
1) It has an awful standard library. You are expected to build everything yourself but having to write your own balanced trees is just going to slow you down. You would want better namespace control to make importing libraries easier.
2) As the parent message points out, C has funky arrays. Had they gone right away with the concept of arrays being a pointer to a capacity as well as the elements of the array, then a compiler switch code of been implemented to do array bounds checking (with a performance penalty of course). In this way, only code that explicitly does pointer math would be highly vulernable to buffer over-flow security flaws. Using [] would be safe as long as you got your buffer pointer is a safe way. Using * by itself would be safe _most_ of the time (no pointer math and funky casts used) especially if you had page zero protected and no structures larger than your page size.
3) It doesn't have "inheritance". I don't care to have real inheritance with methods and everything, just the ability to inherit from a structure and add more fields to it. A special kind of structure would be inheritable and would provide runtime type checking when used with the cast operator.
4) It doesn't have structured exception handling.
Java and C# have 0-4 though they go farther than necessary on #3 in my opinion and the force you to use these features whereas some of them should be optional by turning on or off a compiler switch.
If C had initally had the above features, it would be a pretty sweet language (not withstanding the fact that the size of int and other structures is not gauranteed). You could build objects (aka, add a virtual method table as a slot to a runtime type checkable structure) though I would prefer people see how far you can get without "real" objects. You could add a non-conservative garbage collector with a little help from the compiler, etc.
This hypothetical language, C# and Java could be improved even more with the inclusion of multiple return values and closures though these features are not essential for a "performance language". While I am asking for features, I'd like keyword arguments and easier to use "rest" arguments than what C has. Throw in tail-calls and I'll wet my pants.
Going back to hypothetical C only, multiple return values could pretty much eliminate the need to pass pointers to stack variables (but not heap allocated structures and arrays, naturally) when doing function calls hence eliminating the need for C++ style "references" which I must admit I find to be completely confusing and twisted (probably because I haven't treid that hard, I just hate C++). Automatic dereferencing when using "." or "[]" would eliminate a lot of nasty looking * operations when using a pointers to heap objects.
The problem with both fink and darwinports is that they need to download the source code from dozens of different mirrors *which all seem to have serious bandwidth problems*. I'm lucky to get a mirror that will give me more than 10K/s and so both fink and darwinports are just plain painful to use. When I used to use Redhat linux, I never had problems getting RPMs at a decent speed though maybe even that has changed.
I just wish Apple would use the same mojo they used for the iTunes music store to allow me to download free software that will run on my Mac at something reasonable like 150K/s.
Java's checked exceptions are terrible! What I would like to have instead is a "doesn't throw" declaration. That way I could say a routine doesn't throw a certain type of exception and then I can have the compiler check this based on all of the information it has.
Sounds like Slashdotters want the GPL to be legal but for EULAs to be illegal.
Many garbage collectors are only triggered whenever you allocate an object. This means you can just allocate lots of objects as part of your start-up routine, and then as long as you don't create any more objects, you'll get absolutely no gc pauses. The only negative things I would say about garbage collected languages is that very few implementations give you different gc strategies to choose from and many garbage collected languages make it difficult to know when allocation is occuring. (For example, most Scheme implementations will create garbage when you add two floating-point numbers.) This is more of the problem with the languages and their various implementations and rather than with the concept of garbage collectors. The beauty of plugging in new collectors would be that one option for a "garbage collector" could really just be malloc (and free of course) to make the system more suitable for certain uses.
All chips are designed to run "at the edge" of the frequency upper limit and so AMD doesn't have an inherent advantage because they do more work per clock cycle and Intel does less work per cycle but has a higher frequency. All chip-makers hit the same physical limitations at about the same time and neither has the advantage because they run at a higher or lower frequency today.
The primary determination of clock-speed (besides process technology of course) is the largest number of transistors and the length of the wires in the critical path of each pipeline stage. For a chip with a higher clock-speed using the same process technology, this means that it has less wire or transistors in the longest path of each stage so it can be clocked faster. The presumption is that this is achieved by having more stages or better logic when compared to some other design, etc. but it really doesn't matter as far as the physics are concerned. All chips max out when the frequency is so high that the signals flowing through the circuits don't have enough time to go from one stage to the next and from this perspective, the only thing that matters is how much wire and how many transistors. If AMD was able to make faster chips, they would. Likewise with Intel.
It all boils down to this: if I have path with 10 units of delay and you have all paths with 8 or less units of delay, you will achieve a higher clock-speed if we use the same manufacturing process. Niether design is better for getting sped-up when moving to the next process technology since they use the same transistors and wire and are running at the same edge "node" in the current process technology.
Where AMD *may* have an advantage is that the top speed of chips may start to be effected by the power-consumption since if the chips get too hot, they will melt. Power-consumption for CMOS is determined by the dynamic component (when CMOS gates change their state they burn power) and a static component (determined by the total number of transistors). You used to be able to ignore the static component but as the feature size decreases, the leakage current begins to become quite noticeable. [AMD is using SOI already to help with this problem. Intel is eventually going to introduce its SOI work-alike (the name escapes me because it was invented by a marketing person).] Most advanced chips designs include circuits which burn power all of the time, but I'll assume that both Intel and AMD use the same tricks with the same small percentage of their transistors (and it is the same transistors with a high dynamic power usage anyways since they are important circuits).
If is conceivable that one design, Intels P4 or AMD64, is "more efficient" in this it uses less power both statically and dynamically, to acheive the same computations. At the end of the day, the more efficient processor may be able to compute the result quicker because it won't have to turn itself off just to cool down compared to the less efficient design. Currently this kind of limitation is only present in very small laptops.
However, you can't automatically assume that low frequency means the AMD64 design is more efficient. It may do more wasted work (speculation) per cycle in trying to do more work per cycle. It might have more transistors in its ALUs burning power, etc. One things that hurts Intel is that because they have a longer pipe-line, they have a higher penalty for branch mispredications, but they may just be able to tweak the branch predictor or make it larger to recoup this deficit.
At the end of the day, you'd probably find out that the two chips are about as efficient as each other (and that PowerPC processors are a little bit more efficient since they have much simpler decoders). I know that both AMD chips and Intel chips both burn a lot of power. If AMD sticks with SOI and Intel uses inferior technology, then AMD will win. But Intel has a lot of money and they probably won't get out-classed in technology by anyone.
It sounds an awfully lot like they are planning to build a Mach kernel with message ports and everything.
;)
Maybe he should fork Darwin instead and then I could run it on my iBook.
I agree that if one were to design a language today, they should be able to use real world experience to take the best features from all of the available languages and make a super-language.
I just want to make sure that you aren't saying that language evolution has uniformaly progressed from ok --> good --> better. Some old languages like Lisp were actually pretty advanced but languages that came after them usually didn't borrow the most powerful ideas since that would have made them slower (either that, or the people making those languages don't share my tastes). Examples of powerful features from Lisp/Scheme: generic arithmetic with arbitrary percision integers, closures, powerful macro systems, dynamic evaluation, and first class continuations
Until recently, performance has always been the most important factor but the tide has turned and people consider safety and ease of use to be the important properties of the language. For example, making (basically) every object a hashtable like Python, Ruby, and JavaScript do is really convenient for quickly making programs with fewer declarations or for adding your own properties to objects you get from someone else code, but people avoided dreaming about such a luxury when trying to create a compiler for a 4MHz 8086 machine. Ease of use was secondary to the degree that C compilers of the day had ints that were only 16 bits by default.
Your certainly bring up some good points especially with your hack for doing inheritance. It isn't quite the same thing as true inheritance though because I'll still have to do tons of casts everywhere and thus the compiler essentialy won't do type-checking the way it would if it understood inheritance. If I use your trick with a manually constructed safe cast which I could probably make using the typeof, then I could probably get what I want which is as much static type checking as possible.
My primary problem with C++ is that while it has almost all of the extra features I think are truly important, it also has tons of "features" which I find confusing, useless, and or dangerous. Whenever I have seen large C++ programs, I invariably wish that they were written in Java or C#.
I agree with you that if a subset of C++ is used wisely, then it is in fact a great language (though I still want to get rid of header files as priority number 1). In fact, using C++ with the CLR even makes C++ better. However, if you worked with some of the "programmers" I work with, you would spend all of your time worrying about the messes you would have to endure when they bumbled around with the complicated semantics of C++. I think this is why Java and C# or so popular even though when C++ is used in the right way, it is more or less as good as Java and C#. (I think C++ would also be more popular today if it went through less churn when it was being standardized so that the various compilers were more compatible in the early days.)
C is a pretty decent language to program in (in some ways better than Java --for example it has function pointers), however it has a few substantial short-comings:
0) Header files suck. ".o" files should contain everything needed to get all of the types and function prototypes needed while compiling. The compiler should be smart enough to compile multiple files at he same time to deal with the forward references problem.
1) It has an awful standard library. You are expected to build everything yourself but having to write your own balanced trees is just going to slow you down. You would want better namespace control to make importing libraries easier.
2) As the parent message points out, C has funky arrays. Had they gone right away with the concept of arrays being a pointer to a capacity as well as the elements of the array, then a compiler switch code of been implemented to do array bounds checking (with a performance penalty of course). In this way, only code that explicitly does pointer math would be highly vulernable to buffer over-flow security flaws. Using [] would be safe as long as you got your buffer pointer is a safe way. Using * by itself would be safe _most_ of the time (no pointer math and funky casts used) especially if you had page zero protected and no structures larger than your page size.
3) It doesn't have "inheritance". I don't care to have real inheritance with methods and everything, just the ability to inherit from a structure and add more fields to it. A special kind of structure would be inheritable and would provide runtime type checking when used with the cast operator.
4) It doesn't have structured exception handling.
Java and C# have 0-4 though they go farther than necessary on #3 in my opinion and the force you to use these features whereas some of them should be optional by turning on or off a compiler switch.
If C had initally had the above features, it would be a pretty sweet language (not withstanding the fact that the size of int and other structures is not gauranteed). You could build objects (aka, add a virtual method table as a slot to a runtime type checkable structure) though I would prefer people see how far you can get without "real" objects. You could add a non-conservative garbage collector with a little help from the compiler, etc.
This hypothetical language, C# and Java could be improved even more with the inclusion of multiple return values and closures though these features are not essential for a "performance language". While I am asking for features, I'd like keyword arguments and easier to use "rest" arguments than what C has. Throw in tail-calls and I'll wet my pants.
Going back to hypothetical C only, multiple return values could pretty much eliminate the need to pass pointers to stack variables (but not heap allocated structures and arrays, naturally) when doing function calls hence eliminating the need for C++ style "references" which I must admit I find to be completely confusing and twisted (probably because I haven't treid that hard, I just hate C++). Automatic dereferencing when using "." or "[]" would eliminate a lot of nasty looking * operations when using a pointers to heap objects.
The problem with both fink and darwinports is that they need to download the source code from dozens of different mirrors *which all seem to have serious bandwidth problems*. I'm lucky to get a mirror that will give me more than 10K/s and so both fink and darwinports are just plain painful to use. When I used to use Redhat linux, I never had problems getting RPMs at a decent speed though maybe even that has changed. I just wish Apple would use the same mojo they used for the iTunes music store to allow me to download free software that will run on my Mac at something reasonable like 150K/s.
Java's checked exceptions are terrible! What I would like to have instead is a "doesn't throw" declaration. That way I could say a routine doesn't throw a certain type of exception and then I can have the compiler check this based on all of the information it has.