Virtual Functions and Performance C++

后端 未结 8 570
梦毁少年i
梦毁少年i 2021-01-18 04:10

Before you cringe at the duplicate title, the other question wasn\'t suited to what I ask here (IMO). So.

I am really wanting to use virtual functions in my applicat

8条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-18 04:46

    Extending Charles' answer.

    The problem here is that your loop is doing more than just testing the virtual call itself (the memory allocation probably dwarfs the virtual call overhead anyway), so his suggestion is to change the code so that only the virtual call is tested.

    Here the benchmark function is template, because template may be inlined while call through function pointers are unlikely to.

    template 
    double benchmark(Type const& t, size_t iterations)
    {
      timeval a, b;
      gettimeofday(&a, 0);
      for (;iterations > 0; --iterations) {
        t.getArea();
      }
      gettimeofday(&b, 0);
      return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) -
             (a.tv_sec * (unsigned int)1e6 + a.tv_usec);
    }
    

    Classes:

    struct Regular
    {
      Regular(size_t w, size_t h): _width(w), _height(h) {}
    
      size_t getArea() const;
    
      size_t _width;
      size_t _height;
    };
    
    // The following line in another translation unit
    // to avoid inlining
    size_t Regular::getArea() const { return _width * _height; }
    
    struct Base
    {
      Base(size_t w, size_t h): _width(w), _height(h) {}
    
      virtual size_t getArea() const = 0;
    
      size_t _width;
      size_t _height;
    };
    
    struct Derived: Base
    {
      Derived(size_t w, size_t h): Base(w, h) {}
    
      virtual size_t getArea() const;
    };
    
    // The following two functions in another translation unit
    // to avoid inlining
    size_t Derived::getArea() const  { return _width * _height; }
    
    std::auto_ptr generateDerived()
    {
      return std::auto_ptr(new Derived(3,7));
    }
    

    And the measuring:

    int main(int argc, char* argv[])
    {
      if (argc != 2) {
        std::cerr << "Usage: %prog iterations\n";
        return 1;
      }
    
      Regular regular(3, 7);
      std::auto_ptr derived = generateDerived();
    
      double regTime = benchmark(regular, atoi(argv[1]));
      double derTime = benchmark(*derived, atoi(argv[1]));
    
      std::cout << "Regular: " << regTime << "\nDerived: " << derTime << "\n";
    
      return 0;
    }
    

    Note: this tests the overhead of a virtual call in comparison to a regular function. The functionality is different (since you do not have runtime dispatch in the second case), but it's therefore a worst-case overhead.

    EDIT:

    Results of the run (gcc.3.4.2, -O2, SLES10 quadcore server) note: with the functions definitions in another translation unit, to prevent inlining

    > ./test 5000000
    Regular: 17041
    Derived: 17194
    

    Not really convincing.

提交回复
热议问题