octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: move constructors


From: Daniel J Sebald
Subject: Re: move constructors
Date: Mon, 19 Aug 2019 00:30:49 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

On 8/14/19 6:31 PM, Rik wrote:
On 08/14/2019 02:43 PM, Rik wrote:
On 08/14/2019 11:21 AM, John W. Eaton wrote:
> On 8/14/19 1:05 PM, Rik wrote: > >> This jibes with my sense from the profiling that we are doing a lot of >> unnecessary creation/destruction of objects. >> >> *IF* heavyweight constructors are a problem, then calling them less >> frequently by using move constructors and move assignment operators would >> definitely help. However, that is still a hypothesis. Is there a >> relatively simple way to test this short of re-writing a bunch of classes? >> >> One option might be to place a counter in the constructor, assignment >> operator, and destructor routines for octave_value. >> >> I should also say that I tried implementing a move constructor after >> OctConf2018 and I didn't see any improvement. But, I also could have >> screwed it up and I didn't spend a long time on it. > > Yeah, see the attached simplified version of our Array class. There are a few cases that seem (to me, at least, with my limited understanding) like it should be possible for the compiler to figure out that it can call move constructor or the move assignment operator but it doesn't. But AFAICT, it is following the rules. OTOH, in some cases, the compiler may completely remove calls to the copy constructor or assignment operator even when move constructors are not explicitly defined. This happens for me regardless of the optimization level (using GCC 8.3). > > If we see a large penalty for using atomic reference counting, then we must be performing many operations where we increment and decrement the count. Are we doing many of those operations unnecessarily? If so, and given what I see with the example class, I'm wondering why more of these operations are not eliminated. Can we easily find where they are happening? At least that would be a start to understanding what should be done.
Just to get an idea, I modified the destructor in Array.h to

    ~ArrayRep (void) {
        static long int n = 0;
        std::cerr << "~ArrayRep: " << ++n << "\n";
        delete [] data; }

I find that running an average statement like "x = 1;" causes 40 destructor calls.  That does seem excessive.

A similar experiment with modifying the destructor for octave_value_list shows that we are creating/destroying a lot more of these then I think is necessary given the complexity of the statements.  A simple function call seems to require 9 octave_value_list objects.  An anonymous function is 21.

--Rik

:DATA:

octave:3> y = x + 1;
~octave_value_list: 7782
octave:4> y = sin (1);
~octave_value_list: 7783
~octave_value_list: 7784
~octave_value_list: 7785
~octave_value_list: 7786
~octave_value_list: 7787
~octave_value_list: 7788
~octave_value_list: 7789
~octave_value_list: 7790
~octave_value_list: 7791
octave:5> f = @(x) 2*x
f =

@(x) 2 * x
~octave_value_list: 7792
~octave_value_list: 7793
~octave_value_list: 7794

~octave_value_list: 7795
~octave_value_list: 7796
~octave_value_list: 7797
octave:6> y = f(1)
~octave_value_list: 7798
~octave_value_list: 7799
~octave_value_list: 7800
~octave_value_list: 7801
~octave_value_list: 7802
~octave_value_list: 7803
~octave_value_list: 7804
~octave_value_list: 7805
~octave_value_list: 7806
~octave_value_list: 7807
~octave_value_list: 7808
~octave_value_list: 7809
~octave_value_list: 7810
~octave_value_list: 7811
~octave_value_list: 7812
~octave_value_list: 7813
y =  2
~octave_value_list: 7814
~octave_value_list: 7815
~octave_value_list: 7816
~octave_value_list: 7817
~octave_value_list: 7818
~octave_value_list: 7819



Right; I found the same.  In the comments of this patch

https://savannah.gnu.org/patch/?func=detailitem&item_id=8016#comment2

I basically did the same thing--printed when the reference count was incremented and decremented and when an octave_value was destroyed. I did it for the dbstop command, and got a big list of such calls.

At the time, I didn't want to look into why that is. I was interested in watching the reference count as the octave_value info was transferred across the thread.

Another point about using octave_value to transfer data. By doing so, other parties could build another type of interface if desired. I know there are people out there who have written GUI's for Octave, open source or not. With a simplified interface, it doesn't matter too much if it is Qt on the other side of the link or not. The only reason I can think of getting sophisticated with the GUI/core interaction is if the GUI is to be super-efficient for, say, for simulations or processing low or medium rate data coming from a device connected to a UART or something. But, that is a lot of difficult programming and there aren't the resources for such things. I lean toward making the interface simpler yet flexible.

I'd go with standard library arrays and maps, as well. They are designed to be efficient--expanding memory when needed, holding on to it if the array size shrinks. Same with QLists and QMaps.

Dan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]