- As I get older, I give fewer and fewer fucks. - 3 Updates
- Some C++14 code - 15 Updates
- garbage collection - 5 Updates
- Toggling "Touch Keyboard" On/Off, Firefox and Chrome. - 1 Update
- "Jonathan Blow: "C++ is a weird mess"" - 1 Update
Jeff-Relf.Me @.: Jul 15 10:09PM -0700 |
Jeff-Relf.Me @.: Jul 16 06:05AM -0700 |
Jeff-Relf.Me @.: Jul 16 06:12AM -0700 |
scott@slp53.sl.home (Scott Lurndal): Jul 15 11:51PM >to remember to call free when you've finished with the memory. You just >let the smart pointer go out of scope, and the target vanishes. And this >happens down all your obscure error paths too. For which there is an inevitable cost. In a recent project, we ripped out all the smart pointers because they had a huge performance impact. The code was almost twice as fast after elimination of the smart pointers. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 16 03:47AM +0200 On 16.07.2018 01:51, Scott Lurndal wrote: > For which there is an inevitable cost. In a recent project, we ripped > out all the smart pointers because they had a huge performance impact. The > code was almost twice as fast after elimination of the smart pointers. No offense intended, just that it might help you to hear me thoughts here. It seems likely to me that * the smart pointers were not the performance problem, but measuring a debug build gave nonsense data, and * when the code evolves further the decision to remove smart pointers is going to bite someone, then, very hard in the ass. Uh, arse. Well, let's say the "behind", if that's PC. ;-) Cheers!, - Alf |
Juha Nieminen <nospam@thanks.invalid>: Jul 16 05:19AM > I seized on the word 'maps' and envisioned something more elaborate than > your example, involving structs, vectors and maps in various arrangements. Well, freely substitute std::vector with std::map in my example. It doesn't get any more complicated. Even if you were to use your own custom dynamic data container, its use still doesn't have to become any more complicated since the language gives you the tools to make it as simple to use as std::vector and std::map. > trivial as you suggest. A scripting language (even mine which is lower > level than most) really could handle this stuff trivially and would > probably run rings around any C++ code. How? A scripting language would probably be slower. Besides, the comparison was to C (and the use of generic data containers there), not to some other languages. |
Juha Nieminen <nospam@thanks.invalid>: Jul 16 05:26AM > There are very few usage cases for std::list in C++, and I haven't > encountered any in ~20 years of C++ programming. Each time either > std::deque or std::vector has been a better fit. It's extremely rare, but sometimes std::list *is* the most convenient (and, possibly, even most efficient) solution to a problem. Consider, for example, a video game where an enemy shoots tons of projectiles. These projectiles may hit scenery and objects pretty much at random, at any moment, with no specific order. The enemy also spawns new projectiles almost constantly. Therefore new projectiles are being spawned at a regular basis, and they disappear (and thus should be removed) pretty much at random. As it turns out, std::list is the most convenient data container for this. All the projectiles are put into one, and at each frame you traverse the list and update their positions and check for collisions. Every time a projectile collides with something and is destroyed, you can conveniently remove it from the list. In this situation being able to remove the projectile object from the current position in the list in O(1) is both convenient and efficient (and may well make up for the slight inefficiency of the memory allocations needed for the list elements.) The same cannot be efficiently done with a std::vector or std::deque, where removing the object from it is an O(n) operation. |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 16 08:39AM +0300 On 16.07.2018 2:51, Scott Lurndal wrote: > For which there is an inevitable cost. In a recent project, we ripped > out all the smart pointers because they had a huge performance impact. The > code was almost twice as fast after elimination of the smart pointers. Then you used wrong type of smartpointers, or used them in a wrong place. The fact that you were able to rip them out suggests the latter. Inside a std::map implementation for example there are no smartpointers used as the data structure can manage its data otherwise. |
Ian Collins <ian-news@hotmail.com>: Jul 16 06:04PM +1200 On 16/07/18 11:51, Scott Lurndal wrote: > For which there is an inevitable cost. In a recent project, we ripped > out all the smart pointers because they had a huge performance impact. The > code was almost twice as fast after elimination of the smart pointers. The only real cost with standard smart pointers in an optimised build comes from excessive copying of std::shared_ptr objects. On some targets the resulting atomic increments and decrements are expensive. That's why it's good practice to pass std::shared_ptr by const reverence where possible. Using something like std::unique_ptr to manage the lifetime of an object is a freebie. -- Ian. |
Christian Gollwitzer <auriocus@gmx.de>: Jul 16 09:31AM +0200 Am 16.07.18 um 07:26 schrieb Juha Nieminen: > allocations needed for the list elements.) > The same cannot be efficiently done with a std::vector or std::deque, > where removing the object from it is an O(n) operation. I'm still not convinced a 100%. To store the projectiles, probably a small struct can be used which stores the position and velocity. You could add a single boolean active and pool them. When you want to remove one, you simply set active to false. Most probably you need to do a full pass over all of them anyway to test for collisions and update the position, and inside this loop you can manage and update the active flag. Compacting the buffer can also be combined with this loop. I think that it still needs to be timed if you win anything by using std::list instead of a contiguous buffer with occasional reallocation, i.e. "garbage collection. I agree, however, that std::list is more convenient. Christian |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 16 10:20AM +0200 On 15.07.2018 15:09, Bart wrote: > if c in identstarter then ... > I expect both Python and C++ have a Set implementation so powerful that > it can do anything - except construct simple sets as easily as above). C++ provides just building blocks. Creating the kind of batteries that are included with e.g. Python is much work. I took your remark as an opportunity to yet again code up some set and ranges support in C++. Sort of equivalent code: ----------------------------------------------------------------------------- #include <cppx/stdlib-wrappers/Set_.hpp> // https://github.com/alf-p-steinbach/cppx #include <stdlib/c/stdio.hpp> // https://github.com/alf-p-steinbach/Wrapped-stdlib using namespace std; auto main() -> int { using cppx::Set_; using cppx::Range_; const auto identstarter = Set_<char>{} + Range_{ 'A', 'Z' } + Range_{ 'a', 'z' } + '_' + '$'; const auto identbody = identstarter + Range_{ '0', '9' } - 'Z'; for( const char ch : Range_{ ' ', char( 127 ) } ) { if( in( identbody, ch ) ) { printf( "%c ", ch ); } } printf( "\n" ); } ----------------------------------------------------------------------------- It's not perfect but it's not so bad either, is it? Cheers!, - Alf |
boltar@cylonHQ.com: Jul 16 08:39AM On Fri, 13 Jul 2018 09:09:51 -0700 (PDT) >> C# only runs on windows >No. My music player Roon consists of a Roon Server running on a dedicated >linux box and a Roon app running on an ipad mini, all using C#. Well ok there's Mono. But its god knows how many versions behind and AFAIK doesn't support half of the Windows API so whats the point? If you want a VM language on linux just use java. |
boltar@cylonHQ.com: Jul 16 08:42AM On Fri, 13 Jul 2018 23:27:54 +0100 >to remember to call free when you've finished with the memory. You just >let the smart pointer go out of scope, and the target vanishes. And this >happens down all your obscure error paths too. Given C doesn't have exceptions but only explicit returns then remembering to call free on a local pointer is hardly onorous. >And the copy - once you've taught the object how to copy itself nobody >else has to mess about with memcpy(target, source, sizeof(type)) then >fix any embedded pointers. Yes, I'll give you that, but doing deep copies is often a source of bugs in C++ too. And with the move semantics even more so. |
Bart <bc@freeuk.com>: Jul 16 11:20AM +0100 On 16/07/2018 09:20, Alf P. Steinbach wrote: > } > ----------------------------------------------------------------------------- > It's not perfect but it's not so bad either, is it? No, it doesn't look too bad. (That I could actually follow some C++ for once is a good sign.) But what is the underlying data-structure? Pascal-like sets might use a bitmap so the test for 'in' is a simple bit-test (after checking for range and locating the byte where the bit will be). -- bart |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 16 03:45PM +0300 On 16.07.2018 13:20, Bart wrote: >> using cppx::Range_; >> const auto identstarter = Set_<char>{} >> + Range_{ 'A', 'Z' } + Range_{ 'a', 'z' } + '_' + '$'; [...] > But what is the underlying data-structure? Pascal-like sets might use a > bitmap so the test for 'in' is a simple bit-test (after checking for > range and locating the byte where the bit will be). Alf's Set_ is a template probably taking any type which has a comparison operator defined. C++ has std::bitset which could be used automatically for a limited range datatype like char. Not sure if this actually a case or if it would be a good idea at all, too much automatism is not always good either. Maybe define another class like LimitedRangeSet or something. For comparison, here is a solution using only C++ standard classes. It requires some helper functions to simplify the usage. As Alf said, C++ tends to give you the building blocks, not the ready-made solution. In a proper C++ solution these functions should probably go into a custom class for more encapsulation, this is just a minimal example. #include <iostream> #include <bitset> #include <limits> constexpr char kMin = std::numeric_limits<char>::min(); constexpr char kMax = std::numeric_limits<char>::max(); using set = std::bitset<kMax-kMin+1>; set Range(char a, char b) { set x; while (a<=b) { x.set(a++ - kMin); } return x; } set Elem(char a) { return Range(a, a); } bool In(char c, const set& x) { return x[c-kMin]; } int main() { set identstarter = Range('A', 'Z') | Range('a', 'z') | Elem('_') | Elem('$'); set identbody = (identstarter | Range('0', '9')) & ~Elem('Z'); // exclude Z char c = 'Z'; if (In(c, identstarter)) { std::cout << c << " is in identstarter\n"; } if (In(c, identbody)) { std::cout << c << " is in identbody\n"; } } |
scott@slp53.sl.home (Scott Lurndal): Jul 16 12:51PM >It seems likely to me that >* the smart pointers were not the performance problem, but measuring a >debug build gave nonsense data, and Look - all the engineers on the project have a minimum of 20 years experience, each. They do performance analysis of processors and applications on the scale of operating systems, memcached, machine learning algorithms and RDBMS systems for a living. I think we're perfectly capable of doing performance analysis and mitigation and understanding the difference between production code and whatever a debug build might be (none of us program on windows systems or use VS - for us, a debug build omits -O3). The application doesn't do any signficant I/O, so it is very much CPU-bound. >* when the code evolves further the decision to remove smart pointers is >going to bite someone, then, very hard in the ass. Uh, arse. Well, let's >say the "behind", if that's PC. ;-) Actually, this is one of the common memes here and in the later C++ versions - you seem to think that programmers are naturally incompetent and only useless, ill-performing language enhancements are the solution; whereas the fact is that programmers have been writing viable, secure and performant C++ code for three decades without smart pointers, lambdas and other cruft. It's just not open source. |
scott@slp53.sl.home (Scott Lurndal): Jul 16 12:52PM >where possible. >Using something like std::unique_ptr to manage the lifetime of an object >is a freebie. So is using a regular pointer and understanding the code. |
Manfred <noname@add.invalid>: Jul 16 03:12PM +0200 On 7/16/2018 2:51 PM, Scott Lurndal wrote: > and understanding the difference between production code and whatever > a debug build might be (none of us program on windows systems or use > VS - for us, a debug build omits -O3). Still one question remains: was it unique_ptr or shared_ptr's that you removed (or both)? The difference is relevant. That said, blindly replacing all raw pointers with smart pointers is a misuse, I agree with you need to know what you are doing and choose appropriately. (by the way, you know that with gcc omitting -O3 is equivalent to -O0) |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jul 15 08:09PM -0700 On 7/15/2018 7:47 AM, Andrew Goh wrote: > and that the use of mark and sweep would leave fragmented memory after collection > is there something such as a mark and compact garbage collector? if the simple implementation is difficult perhaps with the combined used of smart pointers? > thanks in advance Think of proxy reference counts: https://groups.google.com/d/topic/lock-free/X3fuuXknQF0/discussion (read all, if interested...) https://groups.google.com/d/topic/lock-free/QuLBH87z6B4/discussion We can amortize the cost of reference counting by keeping multiple objects under a proxy reference count. We can take a reference, then iterate a shi% load of objects without having to mutate anything within them for they say alive during the iteration. We take a reference, and read full steam ahead. Fwiw, RCU is an example of a clever proxy collector optimized for reads, wrt the way it works: https://lwn.net/Articles/262464 (read all!) So, to answer your question, something like RCU can keep everything alive without a full blown heavy handed garbage collector :^) |
bitrex <user@example.net>: Jul 16 01:45AM -0400 On 07/15/2018 10:47 AM, Andrew Goh wrote: > and that the use of mark and sweep would leave fragmented memory after collection > is there something such as a mark and compact garbage collector? if the simple implementation is difficult perhaps with the combined used of smart pointers? > thanks in advance In C++ at least the ideal is that there is no "garbage" to collect. Every resource that's "alive" is there for a reason. When the last context where an object of type Foo needs to exist exits then the object's destructor is called and all the resources it holds (that the object ideally acquired via RAII) are freed automatically. E.g. Java needs a garbage collector because there's only one place you can allocate memory and instantiate resources which is in a heap of some type; when a function call exits there isn't really a good way to "know" without some kind of reference counting whether this resource or that in the heap is still needed? or was it only just used that one time? How do I know without some fashion of metadata C++ "knows" because unlike Java it has a stack and everything that's not on the heap is on the stack, and the policy such as it is is that anything left on the stack when the function call exits is out the door. The stack is there to be used as much as possible as an option of first resort; code which uses the operator new/smart pointers to heap-allocate objects that could fit perfectly well on the stack where the resource is used only within that function call or a nested set of function calls is functionally retarded, just do Object object and pass around by reference or value via the stack, it's cool and fast. IMO whether shared_ptr is 10x slower or not is irrelevant because it has few good use cases in modern C++, modern C++ which uses it all over the place is simply not well-designed code. I think I've used it in something like three or four times. ever. |
bitrex <user@example.net>: Jul 16 01:58AM -0400 On 07/16/2018 01:45 AM, bitrex wrote: > I know without some fashion of metadata > C++ "knows" because unlike Java it has a stack and everything that's not > on the heap is on the stack Or to be pedantic stuff like constexpr objects could be in read-only Flash memory or ROM or EEPROM or something in the case of a Harvard-architecture processor. |
Siri Cruise <chine.bleu@yahoo.com>: Jul 16 12:18AM -0700 In article <c85406c3-1cf2-4802-9421-1421fc8720ee@googlegroups.com>, > than c++ has been around > what's the current state-of-art for 'dynamic' memory management, in the > notion of *garbage collection*? Same as it has always been: reference counting mark sweep ad hoc reference count: Cannot cope with cyclic references naively. Garbage is identified immediately on becoming garbage. mark sweep: Can collect any kind of reference graph. Might introduce noticeable pauses during a mark sweep. ad hoc: Has to be written specifically for each program. > there is Boehm garbage collector > http://www.hboehm.info/gc/ > is this still very popular or is this commonly being used today? Boehm is a mark/sweep collector. Unlike other such collector it examines memory without a map locating pointers, so it examines raw words and guesses whether they are address references. I use it daily. > smart pointers are possibly simply 'good' but i've come across some articles Smart pointers are just a C++ specific technique to sneak in reference counting (the smart pointer hides the count), mark/sweep (the smart pointer maintains the list of base pointers), or ad hoc management. > (e.g. AVL trees), complex hash maps / linked lists, in 'objects linked to > objects' in complex graphs type of scenarios? possibly with circular > references Only mark/sweep can deal with cycles without any special effort by the programmer. Reference counting has to have the programmer ensure at least edge in every cycle is weak. Ad hoc leaves the whole thing to the programmer. > however, bhoehm garbage collector is conservative, and does only mark and > sweep On 64 bit macosx, the lowest address is 4 billion. Integer values are typically smaller than this and real values look like extremely high addresses, so misidentification is rare. > is there something such as a mark and compact garbage collector? if the > simple implementation is difficult perhaps with the combined used of smart > pointers? A compactor has to be able to update all pointers which tends to be lannguage specific. With hundreds of gigabytes of virtual memory, fragmentation is less of a concern. -- :-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @ 'I desire mercy, not sacrifice.' /|\ I'm saving up to buy the Donald a blue stone This post / \ from Metebelis 3. All praise the Great Don! insults Islam. Mohammed |
Andrew Goh <andrewgoh0@gmail.com>: Jul 16 05:52AM -0700 hi all, thanks for all the responses, actually coming from the java world c++ is quite as 'native' to me, i'd guess most 'java programmers' (and so do other similar managed languages) are somewhat spoilt by garbage collection. i'm coming back into c++ for various reasons among which modern multi-core processors increasingly have features that 'high level' languages such as java can only depend on jvm, compiler to 'optimise' the 'low level' codes. one has little influence over if jvm, compiler etc would after all use the features. things that come to mind are the various SIMD, AVX, AVX2, AVX512 instructions and increasingly GPUs as well c++ can use various processor intrinsics, link manual assembler optimised object files, link processor optimised libraries e.g. MKL or TBB https://www.threadingbuildingblocks.org/ or even link as a cilk+ module, which probably make codes more portable and readable with all that vector optimizations thanks for the notes on smart pointers and bhoehm gc i'd certainly try them out https://www.cilkplus.org/ |
Storage Unit <storage.unit@mailinator.com>: Jul 15 10:01PM -0500 > .... > if ( Msg.message == WM_HOTKEY && Msg.wParam == 'K' ) > Launch( L"/Program Files/Common Files/microsoft shared/ink/TabTip.EXE" ), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Things like that are the reason why Windows programs suddenly break when something is not installed to default location. By the way, Jeff, why no HTML posts anymore? -- Emacs OS |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jul 15 08:50PM -0700 On 7/15/2018 1:38 AM, Hergen Lehmann wrote: > different and my understatement of the rather complex IOCP may not be > good enough to fully utilize its power. Although a windows expert > consulted back than did not find anything, i'm doing totally wrong... Fwiw, I used to work with IOCP all the time back in WinNT 4.0. It can scale. However, it has some interesting quirks. https://groups.google.com/d/msg/comp.lang.c++/kAz1VAxD2lI/WqeBMQZtAwAJ https://groups.google.com/forum/#!topic/comp.lang.c++/kAz1VAxD2lI/overview (read all, there is an interesting discussion about IOCP in there...) https://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx (read all) The system is fairly nice. Love the following function: https://docs.microsoft.com/en-us/windows/desktop/FileIO/getqueuedcompletionstatusex-func Grab a bunch of completions at once! Not available back then in nt4. Argh! ;^) |
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