From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,1042f393323e22da X-Google-Attributes: gid103376,public From: eachus@spectre.mitre.org (Robert I. Eachus) Subject: Re: Any research putting c above ada? Date: 1997/05/12 Message-ID: #1/1 X-Deja-AN: 241331940 References: <208C9C61CA05C32B.65D82DC950AAA33A.D68E7B27EB42E98A@library-proxy.airnews.net> <3372D44E.5F44@sprintmail.com> Organization: The Mitre Corp., Bedford, MA. Newsgroups: comp.lang.ada Date: 1997-05-12T00:00:00+00:00 List-Id: In article <3372D44E.5F44@sprintmail.com> "John G. Volan" writes: > So don't turn your nose up so fast about the return-by-copy mechanism in > Ada95 (or in C++ for that matter). Sure, you lose some efficiency, but > you get a lot of safety from that! I strongly agree. First get it working correctly--and that means no memory leaks--then, if necessary force low-level optimizations for efficiency. If you have a good compiler, you may be pleasantly surprised by the areas where you don't have to do any additional work. > Probably, but I think it depends on the particular compiler and > what fancy optimizations it has. I believe a smart compiler can > legally eliminate one of these copies ... but I should let the > compiler gurus have the last word on this. The last word from a compiler guru is that if you have a good compiler and it misses an (obvious to you transformation) there is probably some reason you are unaware of why that optimization is not correct. And even if a compiler guru sees an obvious missing transformation, he will often discover that it was either left out as not useful or as less important than some other case. (I once had one of these where we really had a problem. The correct optimization for well written code prevented an optimization that was much more important if the code was junk. In paticular hoisting invariants out of loops was a big win on "junk" code, but it was preventing some useful strength reductions. We put a switch in the compiler, documented it, and left it at that.) But back to the "obvious" to non-gurus transformations of unbounded function return values. Many of these transformations work well in the absence of threads or tasking, but not so well in the real world that code runs in. It is perfectly fair to tell a user that the code doesn't work because he failed to mark something as volatile or neglected the possibility of a race condition. However it gets you a very bad reputation if the compiler introduces race conditions involving varibles unknown to the user. Whew! Having said all that, suppose the compiler sees a function returning a string. Allocating that string on the heap will require sychronization unless the implementation supports per task heaps, or the user has told the compiler to ignore tasking and threads. Copying the string will be slow for large strings but will be faster than using heap returns for strings up to about 138 characters. (YMMV and probably will, but if you can avoid tasking overhead and the string is in cache, the number gets pretty large.) Attaching the stack frame above the string to its parent's frame is fastest--but you can only do that if the nested function call can be shown to occur a limited number of times in the parent. The average number of characters returned per call over a large sample of code is say 38. So you decide to do the stack frame munging where it can be shown to be safe and otherwise copy the value. Note that you can't do the stack frame munging if you always return strings on the heap. Now a bug report comes in from the field containing a fragment like: function Tail(S: String; I: Integer) return String is begin return S(I..S'Last); end Tail; function Is_Blank(S: String) return Boolean is begin return S := String'(others => ' '); end Is_Blank; ... Big: String(1..10000); for I in Big'Range loop Do_Something; exit when Is_Blank(Tail(S,I)); end loop; Believe me, your most likely response is not to add this fragment to your statistical database. ;-) (There is no resemblence between this code and any actual incident. You would throw up if you saw the original code which was in Pascal...) Similarly, we once had a "performance problem" on the same Pascal compiler. Seemed the highest optimization level thrashed on an 8000 line subroutine doing common subexpression elimination. Yes it did. And after eight hours on a fast CPU, it produced a > 8 Kbyte object file. The next lowest optimization level produced a 250 Kbyte executable which the customer complained was too big. We eventually convinced him to upgrade his memory to solve the thrashing problem. Sigh! -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...