Are c++ features a subset of java features?

I

Ian Collins

Jon said:
Yes. So the advantage compared to retrofitted GC is performance and the
advantage compared to no GC is simplicity.
Coupled with non-deterministic behaviour?
 
J

Jon Harrop

Ian said:
Coupled with non-deterministic behaviour?

GC is no less deterministic than the STL. Indeed, GC typically gives much
better worst case time and memory performance than the STL.
 
I

IR

Jon said:
GC is no less deterministic than the STL. Indeed, GC typically
gives much better worst case time and memory performance than the
STL.

Now comparing oranges and towels...
You're getting more entertaining with each and every post you make!

(ok, ok guys... I'll stop feeding the troll now. I know it's been
annoying for some of you, but I just couldn't stand it :p)


Cheers,
 
I

Ian Collins

Jon said:
GC is no less deterministic than the STL. Indeed, GC typically gives much
better worst case time and memory performance than the STL.
Who's talking about the STL? The STL is the old name for part of the
C++ standard library.

How can GC be "no less deterministic" than the automatic calling of an
object's destructor when it goes out of scope?

Consider a lock object that claims a resource in its constructor and
releases it in the destructor. The point of release is known. How to
you duplicate that behaviour without additional complexity using GC?
 
I

Ian Collins

IR said:
Now comparing oranges and towels...
You're getting more entertaining with each and every post you make!

(ok, ok guys... I'll stop feeding the troll now. I know it's been
annoying for some of you, but I just couldn't stand it :p)
But it is interesting watching the way they change the subject to avoid
answering direct questions :)
 
J

Jon Harrop

Ian said:
Who's talking about the STL?

I am.
The STL is the old name for part of the C++ standard library.

Ok, whatever you kids are calling it these days.
How can GC be "no less deterministic" than the automatic calling of an
object's destructor when it goes out of scope?

The answer depends upon the semantics you are referring to. If you are
referring to allocating and deallocating externals resources then that is
not the purpose of a GC (although they can often be used for that). If you
are referring to the stacking of converse operations then I address that
below. If you are referring to the deallocation performed by a destructor
(e.g. an STL container) then it is a black box, no more deterministic than
a GC.
Consider a lock object that claims a resource in its constructor and
releases it in the destructor. The point of release is known. How to
you duplicate that behaviour without additional complexity using GC?

Wrap the lock and release in a higher-order function and write in
continuation passing style:

let f k x =
lock x;
try k x finally
release x
 
P

Pete Becker

Jon said:
1. If memory management is handled by the compiler and runtime environment,
it can perform hybrid optimisations:

http://lists.tunes.org/archives/gclist/1997-November/001291.html

What are the performance gains, if any, from doing this, and why is it
impossible for a C++ compiler to do something similar?
2. Retrofitting a GC alters the semantics of the language and makes
languages like C++ even less safe and even more error-prone unless you
manage the whole language, in which case performance suffers terribly:

http://gcc.gnu.org/ml/java/1999-q4/msg00467.html

You're quoting an e-mail that says that if the GC isn't implemented
correctly you can get bad performance. Big deal. The e-mail also
suggests how to fix the problem, and it's pretty much a no-brainer.
3. Run-time representation can be tuned for GC if the language was designed
for GC, e.g. tagging vs boxing.

http://pauillac.inria.fr/~xleroy/talks/compilation-agay.pdf

I'm not going to dig through a 90 page paper to find the parts that you
think are relevant.
4. Language implementors can choose to use stack or heap if the language is
designed for GC.

http://citeseer.ist.psu.edu/11526.html

Not as long as the previous, but still, more than I'm going to hunt
through for the parts that you think are relevant.
5. A retrofitted GC cannot move objects to compact the heap, i.e. it will
never be as space-efficient as a real GC.

"Many Java/ML/Scheme implementations have faster garbage collectors that may
move objects..." - Hans Boehm
http://www.hpl.hp.com/personal/Hans_Boehm/gc/nonmoving/html/slide_4.html

Er, he actually says just the opposite, but you've snipped context.
Here's the entire quotation:

Why non-moving? ... Because fundamental
performance considerations don't change
much. Many Java/ML/Scheme implementations
have "faster" garbage collectors that move
objects, but they're not consistently faster.

Besides, he's talking about a particular implementation. Even if he had
actually said what you claim he says, it doesn't support your assertion
that GC "will never work as well" as on a system designed for it. And
you quoted out of context. The actual comment is:
6. Conservative garbage collectors try to make the best of a bad job by
guessing which heap values are pointers.

Look at Boehm's own GC benchmark:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_bench/

"Some Java implementations have similar or better performance"

I'm not going to hunt through those source files to see if that comment
is actually there. But even assuming it's accurate, it doesn't support
your assertion that GC "will never work as well" as on a system designed
for it.
Running Boehm's own benchmark here, Java is as fast as C++ without GC and
twice as fast as C++ with Boehm's GC:

You've already demonstrated that you edit what other people say to suit
your purposes. Show me an objective source with this information.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Jon said:
Languages designed to be garbage collected have more freedom over their
choice of garbage collector, so they will be faster than languages with
retrofitted GCs.

Really? Please point to an objective study that supports this claim. Not
one that simply looks at existing implementations, but considers every
possible way of implementing GC in C++, including possible language
extensions. Unless, of course, you're abandoning your claim that it
"will never work as well."

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Jon said:
I'm sorry but you are asking me to cite evidence to support a claims that
have been widely accepted since about 1959.

You've again snipped the actual context in order to make a rather
different claim. If you go back in this thread, you'll see that you made
the vague claim that after adding GC to C++ with the Boehm collector
"they're still lacking safety." That most certainly hasn't been "widely
accepted since about 1959".

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
I

Ian Collins

Jon said:
Ian Collins wrote:


The answer depends upon the semantics you are referring to. If you are
referring to allocating and deallocating externals resources then that is
not the purpose of a GC (although they can often be used for that). If you
are referring to the stacking of converse operations then I address that
below. If you are referring to the deallocation performed by a destructor
(e.g. an STL container) then it is a black box, no more deterministic than
a GC.
No, it occurs when the object goes out of scope or is explicitly
destroyed. Quite deterministic.
Wrap the lock and release in a higher-order function and write in
continuation passing style:

let f k x =
lock x;
try k x finally
release x
So you have to add the complexity of a try-finally block and the
complexity and potential error of a release.

The C++ way would be
{
lock x;
doStuff
}
 
J

Jon Harrop

Pete said:
What are the performance gains, if any, from doing this, and why is it
impossible for a C++ compiler to do something similar?

Such optimisations require the optimiser in the compiler to know the details
of the memory allocator and collector, i.e. the GC. This is not possible if
the GC has been retrofitted onto the language as a library. The compiler's
optimiser does not have the necessary information to make the
optimisations.
I'm not going to dig through a 90 page paper to find the parts that you
think are relevant.

It seems I really can't make you drink.

"Tagging is a well-known tech-
nique for implementing dynamically-typed languages
(Lisp, Smalltalk). It can be used as a special case of
run-time type inspection, where type information is at-
tached to data structures instead of being passed sepa-
rately, and type expressions are mapped to a small set
of base types, efficiently encoded at the bit level."
http://216.239.59.104/search?q=cach...ging+xleroy&hl=en&gl=uk&ct=clnk&cd=1&ie=UTF-8
Not as long as the previous, but still, more than I'm going to hunt
through for the parts that you think are relevant.

From the abstract: "No stack is used".
Er, he actually says just the opposite, but you've snipped context.

"Because it is hard to move objects for C programs", i.e. retrofitting
limits choices which limits performance.
Here's the entire quotation:

Why non-moving? ... Because fundamental
performance considerations don't change
much. Many Java/ML/Scheme implementations
have "faster" garbage collectors that move
objects, but they're not consistently faster.

Besides, he's talking about a particular implementation.

You cannot benchmark non-specific implementations.
Even if he had
actually said what you claim he says, it doesn't support your assertion
that GC "will never work as well" as on a system designed for it. And
you quoted out of context. The actual comment is:

Is what?
I'm not going to hunt through those source files to see if that comment
is actually there.

Second paragraph of this page:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_bench.html
But even assuming it's accurate, it doesn't support
your assertion that GC "will never work as well" as on a system designed
for it.

I've now given you plenty of direct citations.
You've already demonstrated that you edit what other people say to suit
your purposes.

If you don't believe my timings then run the code for yourself. I posted the
URL and even the compile commands.
Show me an objective source with this information.

Apparently any objective sources are too long for you to read.
 
J

Jon Harrop

Pete said:
You've again snipped the actual context in order to make a rather
different claim. If you go back in this thread, you'll see that you made
the vague claim that after adding GC to C++ with the Boehm collector
"they're still lacking safety." That most certainly hasn't been "widely
accepted since about 1959".

Sorry, you want to know why C++ is unsafe? Try Stroustrup:

http://www.research.att.com/~bs/bs_faq.html#unsafe
 
J

Jon Harrop

Ian said:
No, it occurs when the object goes out of scope or is explicitly
destroyed. Quite deterministic.

We need to clarify. You're saying that the point the destructor call is made
is deterministic. Very true. I was saying that the time taken for the
destructor of an STL container to run is non-deterministic.

You can get the determinism of scope-based deconstruction in other languages
(see below).

Incidentally, can C++ compilers do block reordering optimisations, moving
the scopes around to generate better assembler? Presumably if it alters the
positions of destructor calls this is forbidden.
So you have to add the complexity of a try-finally block and the
complexity and potential error of a release.

The C++ way would be
{
lock x;
doStuff
}

I wasn't clear enough. The code I posted is factored out commonality that
would appear in a library whereas the code you just posted is equivalent to
a use of that.

My code was equivalent to the code you omitted that contains the release in
C++ (it might as well contain the lock as well):

class F {
T x;
F(T x2) : x(x2) { lock x; }
~F() { release x; }
}

You'd use that like this in C++:

{
F f = new F(x);
...
}

The allocation takes the lock and the end of scope guarantees its removal.

The code you posted demonstrates how you might use this. The equivalent for
my code is:

f (fun x -> ...) x

So there is no significant difference in complexity, both are equally
deterministic, both are exception-safe. GC doesn't lose you anything here.

This is actually a common idiom used in many programming languages. I've
been using it recently in F# to constrain the lifetimes of DirectX objects
because the .NET GC is much less deterministic than OCaml's GC.
 
P

Pete Becker

Jon said:
Such optimisations require the optimiser in the compiler to know the details
of the memory allocator and collector, i.e. the GC. This is not possible if
the GC has been retrofitted onto the language as a library.

Oh, now you've changed your assertion from GC in general to GC
implemented as a library.

The compiler's
optimiser does not have the necessary information to make the
optimisations.


It seems I really can't make you drink.

You have to make your case. Citing 90 page papers that talk about a wide
variety of subjects doesn't do that.
"Tagging is a well-known tech-
nique for implementing dynamically-typed languages
(Lisp, Smalltalk). It can be used as a special case of
run-time type inspection, where type information is at-
tached to data structures instead of being passed sepa-
rately, and type expressions are mapped to a small set
of base types, efficiently encoded at the bit level."
http://216.239.59.104/search?q=cach...ging+xleroy&hl=en&gl=uk&ct=clnk&cd=1&ie=UTF-8

And what makes you think a C++ compiler can't do this?
From the abstract: "No stack is used".

So what?
"Because it is hard to move objects for C programs", i.e. retrofitting
limits choices which limits performance.


You cannot benchmark non-specific implementations.

Nope. But benchmarking particular implementations doesn't establish your
claim that GC in C++ "will never work as well" as in a language designed
for it.

Is a leftover part that didn't get properly edited.
Second paragraph of this page:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_bench.html


I've now given you plenty of direct citations.

Most of which don't say what you claim they say, and don't support the
claim that you made.
If you don't believe my timings then run the code for yourself. I posted the
URL and even the compile commands.


Apparently any objective sources are too long for you to read.

So, you don't have an objective source that supports your claimed timings.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Jon said:
Sorry, you want to know why C++ is unsafe? Try Stroustrup:

No, I want to know what it is about C++ that you claim has been "widely
accepted since about 1959."

And note that that page talks about violating type safety. That wasn't
on your list of unsafe features. So are you now changing your definition
of safety?

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
I

Ian Collins

Jon said:
We need to clarify. You're saying that the point the destructor call is made
is deterministic. Very true. I was saying that the time taken for the
destructor of an STL container to run is non-deterministic.
How so and how would GC change that?
I wasn't clear enough. The code I posted is factored out commonality that
would appear in a library whereas the code you just posted is equivalent to
a use of that.

My code was equivalent to the code you omitted that contains the release in
C++ (it might as well contain the lock as well):

class F {
T x;
F(T x2) : x(x2) { lock x; }
~F() { release x; }
}

You'd use that like this in C++:

{
F f = new F(x);

F f(x);
...
}

The allocation takes the lock and the end of scope guarantees its removal.

The code you posted demonstrates how you might use this. The equivalent for
my code is:

f (fun x -> ...) x

So there is no significant difference in complexity, both are equally
deterministic, both are exception-safe. GC doesn't lose you anything here.
I'm not sure what yo are saying here, if an exception is thrown, how is
the lock released?
 
J

Jon Harrop

Ian said:
How so and how would GC change that?

The STL does a lot of magic inside its black box in order to improve
performance, using custom allocators. The time they take to execute is
unpredictable. So I'm saying that GC is no worse than that. IME, GC can be
significantly better for worst case (OCaml vs STL).
...
F f(x);

Oops. :)
I'm not sure what yo are saying here, if an exception is thrown, how is
the lock released?

In the C++, the destructor is called as the exception handler unwinds past
the scope. In the ML, the finally clause is called as the exception handler
unwinds past the cope. So both approaches release the lock when an
exception is thrown. There isn't really much difference between the two.
 
J

Jon Harrop

Pete said:
Oh, now you've changed your assertion from GC in general to GC
implemented as a library.

You spoke of "language extensions" elsewhere. Now you want to alter the
compiler (and the language's semantics) so that it can support GC. These
are all good ideas. Indeed, they are necessary to achieve competitive
performance. But the result will no longer be "C++".
And what makes you think a C++ compiler can't do this?

If it did you would have a 31- or 63-bit int type, as OCaml does. I believe
that is no longer C++.
Nope. But benchmarking particular implementations doesn't establish your
claim that GC in C++ "will never work as well" as in a language designed
for it.

Are you now happy that the current Boehm GC is slower than other GCs?
Most of which don't say what you claim they say, and don't support the
claim that you made.

These are some of the many optimisations that other languages have done and
this is the reason they are faster. As we have discussed, these
optimisations cannot be applied to C++.
So, you don't have an objective source that supports your claimed timings.

Apart from Boehm's results and my results? Your results?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top