octave-maintainers
[Top][All Lists]
Advanced

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

Re: move constructors


From: Rik
Subject: Re: move constructors
Date: Wed, 14 Aug 2019 15:31:21 -0700

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




reply via email to

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