Mel <mel@zzzzz.com>: Aug 30 07:42AM +0200 On Thu, 29 Aug 2019 11:02:30 +0200, David Brown > One thing that I gather Rust does well, that C++ has trouble with, is > that when you do the Rust equivalent of std::move'ing something, any > attempt to use the moved-from object is flagged by the compiler. I > think that would be good to spot in C++. Rust move is built into language. Moved objects destructor is not called. -- Press any key to continue or any other to quit |
Mel <mel@zzzzz.com>: Aug 30 08:04AM +0200 On Thu, 29 Aug 2019 13:29:11 -0700, Keith Thompson <kst-u@mib.org> wrote: > > On 29/08/2019 04:36, Melzzzzz wrote: > [...] > >> Rust is nowhere near C. Actually, nowhere near C++. It is nice language, > >> but not for low level programming. During years they ditched GC and most > >> of the things that cripples determinism and performance, it is ok, but > >> without pointer arithmetic and null pointers it is high level language. > >> Having to convert pointer to int and back in order to perform arithmetic > What's terrible about it? Rust doesn't particularly need pointer > arithmetic; unlike C, it's array indexing isn't defined in terms of > pointers. You need pointers for low level things. In rust you need unsafe blocks for almost anything. -- Press any key to continue or any other to quit |
Mel <mel@zzzzz.com>: Aug 30 08:07AM +0200 On Thu, 29 Aug 2019 14:54:18 +0200, Bonita Montero > > Rust is nowhere near C. Actually, nowhere near C++. It is nice language, > > but not for low level programming. During years they ditched GC and most > > of the things that cripples determinism and performance, ... > Rust has no GC, but works with counted references. Yes, but it is not much used. Box, owned reference is built in, i zhink that rc is not built in -- Press any key to continue or any other to quit |
Mel <mel@zzzzz.com>: Aug 30 08:10AM +0200 On Thu, 29 Aug 2019 06:08:13 -0700 (PDT), Öö Tiib<ootiib@hot.ee> wrote: > > > ""Rust is the future of systems programming, C is the new Assem= > bly": > > > Intel principal engineer, Josh Triplett" https://hub.packtpub.com/rust-is-the-future-of-systems-programming-c-is = > > > "At Open Source Technology Summit (OSTS) 2019, Josh Triplett, a > > > Principal Engineer at Intel gave an insight into what Intel is > > > contributing to bring the most loved language, Rust to full parity with= > > > C. In his talk titled Intel and Rust: the Future of Systems Programming= > , > > > he also spoke about the history of systems programming, how C became th= > > How about, instead: > > We take C; > > We add some features to support things like bounds-checked arrays and > > similar; > > We mostly call it done. > Rust supports lot of interesting safety features (like RAII, smart pointers= > , > ownership, generics, move semantics, thread safety). > Adding some safe features at side does not help as history with C++ shows. > Result is bigger language with all the unsafe stuff still there and valid. > OTOH if to cripple the unsafe features a bit then result is some kind of > fourth language that is neither C, C++ nor Rust. Rust generics are interface based. You cant do anything with generic type unless you tell which interfaces satisfies. -- Press any key to continue or any other to quit |
Keith Thompson <kst-u@mib.org>: Aug 29 11:11PM -0700 >> arithmetic; unlike C, it's array indexing isn't defined in terms of >> pointers. > You need pointers for low level things. You need pointer *arithmetic* for far fewer things than you need pointers for. > In rust you need unsafe > blocks for almost anything. So use unsafe blocks. -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */ |
Mel <mel@zzzzz.com>: Aug 30 08:13AM +0200 On Thu, 29 Aug 2019 14:53:05 +0200, Bonita Montero > Rust is nice, but Rust has no exceptions. I wouldn't like to evaluate > this combined error- and return-values after each function-call that > might fail. That's Rust advantage. Returnig discriminated union is right way for handling errors. Rust has syntactic sugar in that. Latest proposal for c++ exceptions leans toeard that solution. -- Press any key to continue or any other to quit |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 08:38AM +0200 > Returnig discriminated union is right way for handling errors. NO, that's a mess. Exceptions are by far more comfortable. The best variant are the distinction between checked and unchecked exceptions in Java. |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 08:51AM +0200 > NO, that's a mess. Exceptions are by far more comfortable. > The best variant are the distinction between checked and > unchecked exceptions in Java. And exceptions are more performant for the performance-relevant case that no exception is thrown with table-driven excepion-handling. The code-path that is processed when no exception is thrown is almost as efficient as if there isn't any exception-handling (nearly zero-over- head). |
"Öö Tiib" <ootiib@hot.ee>: Aug 30 01:00AM -0700 On Friday, 30 August 2019 09:11:01 UTC+3, Mel wrote: > > kind of fourth language that is neither C, C++ nor Rust. > Rust generics are interface based. You cant do anything with > generic type unless you tell which interfaces satisfies. Perhaps I don't understand what you mean. Can you bring example? The main point of generics seems to work in Rust about like in C++ templates. There are generic functions, data types and methods. Instantiations of these work like concrete functions, data types and methods. It is more clear, efficient and/or type-safe than what can be done in C. Type erasure through "void*" or "..." function parameters is type- unsafe and can be inefficient. Code generated with preprocessor can be type safe and efficient but might have unneeded verbosity in interface or to be hard to debug. So it is often better to have copy-paste code in C. |
Mel <mel@zzzzz.com>: Aug 30 10:13AM +0200 On Fri, 30 Aug 2019 08:51:21 +0200, Bonita Montero > that no exception is thrown with table-driven excepion-handling. The > code-path that is processed when no exception is thrown is almost as > efficient as if there isn't any exception-handling (nearly zero-over- > head). Exceptions take space or time, there is no escape, and they are non deterministic... -- Press any key to continue or any other to quit |
David Brown <david.brown@hesbynett.no>: Aug 30 10:14AM +0200 On 29/08/2019 22:29, Keith Thompson wrote: > What's terrible about it? Rust doesn't particularly need pointer > arithmetic; unlike C, it's array indexing isn't defined in terms of > pointers. (Again, let me note that I know little about Rust - I've read some stuff, but never used it. So if I get things wrong about it, I hope to be corrected.) As you say in your other post, pointer arithmetic isn't actually used that much in C or C++, once you discount array access and iterators which would be handled in a more "high level" manner in a non-C language. But sometimes - even if it is only occasionally - it /is/ useful. This can be especially true in low-level and systems code, which apparently is a target for Rust. The whole idea of Rust is to be "safer" than C - it aims to turn logical errors such as misuse of pointers, confusion about owners, etc., into compiler errors. That is a great ambition. But to work properly, you have to follow the rules - workarounds that go outside those rules should be as limited as possible, and strongly discouraged if they can't be blocked by tools. The language seems to be saying "We guarantee your code will avoid null pointer dereferences, buffer overflows, use after free, memory leaks, and all the pointer-related problems that plague C programmers." So far, so good. Then it says "We realise that is too limiting sometimes, so here are the ways to cheat, hack, and mess about under the hood". Your guarantees are out the window, and you are back to /exactly/ the same situation as you have in C - design carefully, code carefully to keep your code safe, because the language and tools won't do it for you. So it is not so much the idea of doing pointer arithmetic manually as integer arithmetic that concerns me (though it might be a step lower level than C's pointer arithmetic). It is the idea that the language allows it and that it is considered an acceptable solution that bothers me. |
Mel <mel@zzzzz.com>: Aug 30 10:16AM +0200 On Fri, 30 Aug 2019 01:00:48 -0700 (PDT), Öö Tiib<ootiib@hot.ee> wrote: > > generic type unless you tell which interfaces satisfies. > Perhaps I don't understand what you mean. Can you bring example? > The main point of generics seems to work in Rust about like in C++ Not even close. Imagin that you have to cite what abstract base classes tvpe inherits, and only thing you can do with type is trough interface... -- Press any key to continue or any other to quit |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 10:18AM +0200 >> head). > Exceptions take space or time, there is no escape, and they are non > deterministic... Computers are always deterministic. ;-) But trowing exceptions is slow. But the case when we have a resouce- or I/O-collapse isn't performance-relevant, i.e. it doesn't matter if throwsing an exception lasts 10 or 1.000 clock-cycles. |
"Öö Tiib" <ootiib@hot.ee>: Aug 30 01:26AM -0700 On Friday, 30 August 2019 11:16:32 UTC+3, Mel wrote: > Not even close. Imagin that you have to cite what abstract base > classes tvpe inherits, and only thing you can do with type is trough > interface... The examples in documentation ... <https://doc.rust-lang.org/book/ch10-00-generics.html> ... are like that: // generic type struct Point<T> { x: T, y: T, } // generic method of generic type impl<T> Point<T> { fn x(&self) -> &T { &self.x } } // usage fn main() { let p = Point { x: 5, y: 10 }; println!("p.x = {}", p.x()); } That does not seem to fit with what you describe. |
Mel <mel@zzzzz.com>: Aug 30 10:31AM +0200 On Fri, 30 Aug 2019 10:18:02 +0200, Bonita Montero > >> And exceptions are more performant for the performance-relevant case > >> that no exception is thrown with table-driven excepion-handling. The > >> code-path that is processed when no exception is thrown is almost as > > zero-over- > >> head). > > Exceptions take space or time, there is no escape, and they are non > But trowing exceptions is slow. But the case when we have a resouce- > or I/O-collapse isn't performance-relevant, i.e. it doesn't matter > if throwsing an exception lasts 10 or 1.000 clock-cycles. I am not talking when you throw. -- Press any key to continue or any other to quit |
Mel <mel@zzzzz.com>: Aug 30 10:33AM +0200 On Fri, 30 Aug 2019 01:26:49 -0700 (PDT), Öö Tiib<ootiib@hot.ee> wrote: > > > > generic type unless you tell which interfaces satisfies. > > > Perhaps I don't understand what you mean. Can you bring example? > > > The main point of generics seems to work in Rust about like in C++ > > Not even close. Imagin that you have to cite what abstract base > > classes tvpe inherits, and only thing you can do with type is trough > println!("p.x = {}", p.x()); > } > That does not seem to fit with what you describe. Try to do something with x... -- Press any key to continue or any other to quit |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 10:39AM +0200 >> or I/O-collapse isn't performance-relevant, i.e. it doesn't matter >> if throwsing an exception lasts 10 or 1.000 clock-cycles. > I am not talking when you throw. The non-throw-case takes almost no or no performance. Evaluating return-codes is simply a magnitude slower. |
Mel <mel@zzzzz.com>: Aug 30 10:43AM +0200 On Fri, 30 Aug 2019 10:39:19 +0200, Bonita Montero > >> Computers are always deterministic. ;-) > >> But trowing exceptions is slow. But the case when we have a resouce- > >> or I/O-collapse isn't performance-relevant, i.e. it doesn't matter > >> if throwsing an exception lasts 10 or 1.000 clock-cycles. > > I am not talking when you throw. > The non-throw-case takes almost no or no performance. That's no true. You have to install handlers evrry time or prepare tbla for each function at program start... > Evaluating return-codes is simply a magnitude slower. This is especially not true. -- Press any key to continue or any other to quit |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 10:47AM +0200 >> Evaluating return-codes is simply a magnitude slower. > This is especially not true. No, this is true. You don't simply unterstand the implications of table-driven exception handling or table-driven exception-handling at all. |
David Brown <david.brown@hesbynett.no>: Aug 30 11:41AM +0200 On 30/08/2019 10:47, Bonita Montero wrote: >>> Evaluating return-codes is simply a magnitude slower. >> This is especially not true. > No, this is true. I take it you have measured this yourself? You have sample code, measurements, statistics to back up this very specific claim? Or is it just based on "something you read somewhere", repeated in the hope that people will believe you more the second time? > You don't simply unterstand the implications of table-driven > exception handling or table-driven exception-handling at all. I expect Mel does understand it. I am less convinced /you/ do. Different error handling techniques have their pros and cons. Anyone claiming one method is faster, safer, clearer, easier than other methods is guaranteed to be /wrong/. They will have different balances, and there is no solution that is the "best" in all situations, or the best in all ways. Table-driven exception handling tends to be efficient at run-time when exceptions are not thrown, when you are running on larger processors (like x86), and when you have no issues with code space. That makes it a good choice (from the efficiency viewpoint) on PC programming. But you can also find that the possibility of exceptions passing through functions can affect their efficiency, even if they don't throw or catching anything directly - it can affect ordering and optimisation of the code by the compiler. It can affect the re-use of stack slots as the compiler has to track all possible exception points and be able to unwind correctly. On resource-constrainted systems, this kind of thing can lead to unwind tables that are bigger than the actual code size - a horrible level of inefficiency that is unacceptable in many cases. And while table-driven exception handling does not need extra instruction codes (just data tables) for functions that pass on exceptions without handling them, you need plenty of extra code - and run-time - when throwing the exception, or when catching it. Error handling via return codes, on the other hand, uses minimal extra code space in functions that raise or handle the errors - usually less overhead than for throwing or catching exceptions. It is certainly going to be much faster when errors do occur. But you have to have some way of passing on errors in functions between the "thrower" and the "catcher". That means more explicit source code, but more efficient object code. Each technique has, as I said, its pros and cons. And there are lots of reasons why one might pick one method over the other beyond efficiency - do you want your error handling clear and explicit, or automatic and hidden? Which is easier to get right, and which is harder to get wrong? But one thing we can be sure of - Sutter would not have started the process of getting "Zero-overhead deterministic exceptions" into C++ if current C++ exceptions were as ideal as suggested. And while Sutter's ideas here may come to naught, and he can be as wrong as anyone else, I am more inclined to listen to his thoughts than those of Bonita. |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 30 11:56AM +0200 > I expect Mel does understand it. I am less convinced /you/ do. Disassemble the code that calls a fuction that might throw an exceptions with an without enabled EH. The difference is only, that the optimiza- tions around that call might be slightly weakened; that's all. But that usually doesn't outweigh the overhead against manually evaluating return-codes. > Different error handling techniques have their pros and cons. Anyone > claiming one method is faster, safer, clearer, easier than other methods > is guaranteed to be /wrong/. 1. Table-driven EH is usually faster. 2. I didn't say that it is safer or clearer, but it is much more convenient. 3. When you come to the excepion-handling mechanism like in Java with checked and unchecked exceptions, you get the best solution. But for compatibility-reasons with C this isn't possible in C++. > exceptions are not thrown, when you are running on larger processors > (like x86), and when you have no issues with code space. That makes it > a good choice (from the efficiency viewpoint) on PC programming. Almost right, but it doesn't depend on the performance of the CPU. Even on small CPUs the performance of processing a resurce- or I/O -collapse doesn't count. > the code by the compiler. It can affect the re-use of stack slots as > the compiler has to track all possible exception points and be able to > unwind correctly. The loss of optimization-opportunities with table-driven exception -handling is very slight. And the cost is of course not so high as handling return-codes manually. > On resource-constrainted systems, this kind of thing can lead to unwind > tables that are bigger than the actual code size - a horrible level of > inefficiency that is unacceptable in many cases. That's true, but then you wouldn't use C++. > Error handling via return codes, on the other hand, uses minimal extra > code space in functions that raise or handle the errors - usually less > overhead than for throwing or catching exceptions. 1. This case isn't performance relevant. 2. Yo cannot say that this is always true. The thing is simply that there might be a number of return-codes evaluated at each call-level which might result in a higher total CPU-time. |
David Brown <david.brown@hesbynett.no>: Aug 30 01:08PM +0200 On 30/08/2019 11:56, Bonita Montero wrote: > tions around that call might be slightly weakened; that's all. But that > usually doesn't outweigh the overhead against manually evaluating > return-codes. There is no doubt that exceptions are aimed at having minimal run-time cost when they are not thrown. But it is important to realise that /minimal/ is not /zero/. >> claiming one method is faster, safer, clearer, easier than other methods >> is guaranteed to be /wrong/. > 1. Table-driven EH is usually faster. Usually it is faster when exceptions are not thrown, but a lot slower when they /are/ thrown. But "usually" is not "always". And for some situations, it is the worst case performance - the speed when there is a problem - that is critical. I'm happy with a claim "Table driven exceptions are generally faster, when there are no errors, than other handling techniques for typical code on PC's". What I am /not/ happy with is "Exception handling is faster than other error return techniques". > 2. I didn't say that it is safer or clearer, > but it is much more convenient. Fair enough - though convenience is also a subjective matter. > 3. When you come to the excepion-handling mechanism like in Java > with checked and unchecked exceptions, you get the best solution. > But for compatibility-reasons with C this isn't possible in C++. Checked exceptions - where the type of exceptions that a function may throw or pass on is part of the signature - are safer, clearer and more efficient. (Compilers can use tables or code branches, whichever is most convenient). But they involve more explicit information, which some people like and others dislike. And they can't pass through functions compiled without knowledge of the exceptions - such as C functions compiled by a C compiler. > Almost right, but it doesn't depend on the performance of the CPU. > Even on small CPUs the performance of processing a resurce- or I/O > -collapse doesn't count. Incorrect. Performance under the worst case is often a critical feature of high reliability systems. It is precisely because the performance exception handling is difficult to predict or measure that exceptions are banned in most such systems. > The loss of optimization-opportunities with table-driven exception > -handling is very slight. And the cost is of course not so high as > handling return-codes manually. That may often be the case, but I would be very wary of generalising too much. >> tables that are bigger than the actual code size - a horrible level of >> inefficiency that is unacceptable in many cases. > That's true, but then you wouldn't use C++. Nonsense. There are many good reasons to use C++, and many features that can be used, without leading to any inefficiency or bloat. >> code space in functions that raise or handle the errors - usually less >> overhead than for throwing or catching exceptions. > 1. This case isn't performance relevant. Often not - but you are wrong to generalise like that. And you can equally well argue that since exception handling is often used in cases where you are dealing with I/O, the performance cost of manual return code checks is negligible and therefore irrelevant with such code. > 2. Yo cannot say that this is always true. The thing is simply that > there might be a number of return-codes evaluated at each call-level > which might result in a higher total CPU-time. Yes, I have already mentioned that return code checking usually involves some handling at functions along the chain between the "thrower" and the "catcher". |
Paavo Helde <myfirstname@osa.pri.ee>: Aug 30 02:08PM +0300 On 30.08.2019 11:43, Mel wrote: > for each function at program start... >> Evaluating return-codes is simply a magnitude slower. > This is especially not true. Your information is out of date for a couple of decades. The current C++ compilers have implemented zero cost exceptions (in the no-throw path) already long time ago. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 29 08:14PM -0400 On 8/29/19 2:14 PM, Stefan Große Pawig wrote: > found only the QMap<QString, QVariant> as baked-in return value and then > assumed that this was the only map type that could be stored in a > QVariant? The key point is that the author of the code freely chose to declare the part map as QMap<QString, QVariant>, where the QVariant was used exclusively to hold integers. He also freely choose to declare the message map as QMap<QString, QVariant>, where the QVariant was used to store a part map. There was no code outside the code he wrote which gave him any excuse for using QVariant for both purposes - no code outside of what he wrote used QVariant to interface with the code he did wrote. Yes, he did use toMap(), to extract the map from the QVariant, but he was the one who wrote the code to put the map into the QVariant. If he'd used QMap<QString, int> for the part map, and QMap<QSTring, QMap<QString, int> > for the message map, it would all have worked fine (except for the bug that I fixed), and he would have been able to extract the map directly, rather than by calling toMap(). So why did he use QVariant instead? I'm getting the impression that he used QVariant without bothering to consider whether it was actually needed. |
David Brown <david.brown@hesbynett.no>: Aug 30 08:28AM +0200 On 30/08/2019 02:14, James Kuyper wrote: > extract the map directly, rather than by calling toMap(). So why did he > use QVariant instead? I'm getting the impression that he used QVariant > without bothering to consider whether it was actually needed. I can imagine a few possible explanations. One is that, as I mentioned earlier, either the code or the programmer comes from a background of dynamically typed language - he may simply have felt comfortable with variant types. Perhaps he was less used to complex types and found "QMap<QString, QVariant>" to be simpler (in his eyes) than "QMap<QSTring, QMap<QString, int> >". For a long time, templates had a reputation for program size bloat in C++. (In the failed "EC++" "Embedded C++" standard, templates were banned for that reason. Though $DEITY only knows why namespaces were banned too.) Some people were left with the impression that you should avoid instantiating too many different template types, to reduce code bloat and duplication. Maybe he thought re-using a single map type was more efficient in program size than using two different types. (I'm not suggesting that this is a /good/ reason, even if it were the case that it would give smaller code - something I doubt.) |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment