Aussie AI

Appendix C: Source Code

  • Book Excerpt from "C++ Ultra-Low Latency: Multithreading and Low-Level Optimizations"
  • by David Spuler, Ph.D.

Appendix C: Source Code

Tester Object Instrumentation Class

This code is for “object instrumentation” that can be useful for performance analysis, and also for debugging and unit testing.

Here’s a test usage to see what constructors and move operations are performed by push_back in the std::vector class:

    Tester::reset_counters();
    std::vector<Tester> vectest4;
    for (int i = 1; i <= 100; i++) 
        vectest4.push_back(i);
    Tester::print_report();

Here’s the full code:

    class Tester {
    private:  // Static data members
        static bool traceall_;
        static int count_default_constructor;
        static int count_copy_constructor;
        static int count_move_constructor;
        static int count_copy_assignment;
        static int count_move_assignment;
        static int count_destructor;
        static int count_int_constructor;

    private:  // Object data members
        int ival_;
        bool trace_;

    public:
        Tester() {
            ival_ = 0;
            count_default_constructor++;
            trace_ = false;
            if (traceall_) {
                cout << "Tester: default constructor: " << ival_ << endl;
            }
        }

        Tester(int val) {
            count_int_constructor++;
            ival_ = val;
            trace_ = false;
            if (traceall_) {
                cout << "Tester: int constructor: " << ival_ << endl;
            }
        }

        Tester(const Tester &other)  // Copy constructor
        {
            ival_ = other.ival_;
            trace_ = other.trace_;
            count_copy_constructor++;
            if (trace_ || traceall_) {
                cout << "Tester: copy constructor: " << ival_ << endl;
            }
        }

        Tester(Tester&& other) noexcept  // Move constructor
        {
            ival_ = other.ival_;
            trace_ = other.trace_;
            other.ival_ = -1;  // Invalidate moved data
            count_move_constructor++;
            if (trace_ || traceall_) {
                cout << "Tester: move constructor: " << ival_ << endl;
            }
        }

        Tester& operator=(const Tester& other)  // Copy assign
        {
            count_copy_assignment++;
            if (this != &other) {  // Avoid aliasing
                ival_ = other.ival_;
                if (trace_ || traceall_) {
                    cout << "Tester: copy assignment: " << ival_ << endl;
                }
            }
            else {
                if (trace_ || traceall_) {
                    cout << "Tester: copy assignment aliasing: " << ival_ << endl;
                }
            }
            return *this;
        }

        Tester& operator=(Tester&& other) noexcept  // Move assign
        {
            count_move_assignment++;
            if (this != &other) {  // Avoid aliasing
                ival_ = other.ival_;
                if (trace_ || traceall_) {
                    cout << "Tester: move assignment: " << ival_ << endl;
                }
            }
            else {
                if (trace_ || traceall_) {
                    cout << "Tester: move assignment aliasing: " << ival_ << endl;
                }
            }
            other.ival_ = -1;  // Invalidate moved data
            return *this;
        }

        ~Tester()
        {
            count_destructor++;
            if (trace_ || traceall_) {
                cout << "Tester: destructor: " << ival_ << endl;
            }
            ival_ = -1;  // Safety
        }

        // Equality operators
        bool operator==(const Tester& other) { return ival_ == other.ival_; }


        // Setters for object members
        void trace(bool bval) { trace_ = bval; }

        // Setters for static data members
        static void traceall(bool bval) { traceall_ = bval; }
        static void reset_counters() {
            count_default_constructor = 0;
            count_copy_constructor = 0;
            count_move_constructor = 0;
            count_copy_assignment = 0;
            count_move_assignment = 0;
            count_destructor = 0;
            count_int_constructor = 0;
        }
        static void print_report() {
            cout << "Tester Count Report" << endl;
            cout << "- Default constructor: " << count_default_constructor << endl;
            cout << "- Int constructor: " << count_int_constructor << endl;
            cout << "- Copy constructor: " << count_copy_constructor << endl;
            cout << "- Move constructor: " << count_move_constructor << endl;
            cout << "- Copy assignment: " << count_copy_assignment << endl;
            cout << "- Move assignment: " << count_move_assignment << endl;
            cout << "- Destructor: " << count_destructor << endl;
        }

        static void selftest() {
            // Constructors should equal destructors
            // ... but move constructors don’t increase the count
            int errors = 0;
            int total_constructors = count_default_constructor + count_int_constructor + count_copy_constructor;
            if (total_constructors != count_destructor) {
                if (total_constructors > count_destructor) {
                    cout << "Tester selftest: constructors (" << total_constructors 
                         << ") more than destructors (" << count_destructor << ")" << endl;
                    errors++;
                }
                else {
                    cout << "Tester selftest: destructors (" << count_destructor 
                         << ") more than constructors (" << total_constructors << ")" << endl;
                    errors++;
                }
            }

            if (errors == 0) {
                cout << "Tester selftest: no errors found" << endl;
            }
        }

    };

    // Define Tester static data members
    bool Tester::traceall_ = false;
    int Tester::count_default_constructor = 0;
    int Tester::count_copy_constructor = 0;
    int Tester::count_move_constructor = 0;
    int Tester::count_copy_assignment = 0;
    int Tester::count_move_assignment = 0;
    int Tester::count_destructor = 0;
    int Tester::count_int_constructor = 0;

Intercepted new and delete

This source code is the global scope intercept functions for the new and delete operators. The library tracks basic statistics about calls and bytes allocated.

    // Global counters
    unsigned long int s_new_count = 0;
    unsigned long int s_newarr_count = 0;
    unsigned long int s_delete_count = 0;
    unsigned long int s_deletearr_count = 0;
    unsigned long int s_new_bytes = 0;
    unsigned long int s_newarr_bytes = 0;

    void memory_reset_counters()
    {
        s_new_count = 0;
        s_newarr_count = 0;
        s_delete_count = 0;
        s_deletearr_count = 0;
        s_new_bytes = 0;
        s_newarr_bytes = 0;
    }

    void memory_report()
    {
        cout << "MEMORY CALLS REPORT" << endl;
        cout << "- new calls: " << s_new_count << endl;
        cout << "- new[] calls: " << s_newarr_count << endl;
        cout << "- delete calls: " << s_delete_count << endl;
        cout << "- delete[] calls: " << s_deletearr_count << endl;
        cout << "MEMORY SIZE REPORT" << endl;
        cout << "- new bytes: " << s_new_bytes << endl;
        cout << "- new[] bytes: " << s_newarr_bytes << endl;
    }

    void* operator new(size_t n)
    {
        s_new_count++; 
        s_new_bytes += n;
        return malloc(n);
    }

    void* operator new[](size_t n)
    {
        s_newarr_count++;
        s_newarr_bytes += n;
        return malloc(n);
    }

    void operator delete(void* v)
    {
        s_delete_count++;
        free(v);
    }

    void operator delete[](void* v)
    {
        s_deletearr_count++;
        free(v);
    }

 

Online: Table of Contents

PDF: Free PDF book download

Buy: C++ Ultra-Low Latency

C++ Ultra-Low Latency C++ Ultra-Low Latency: Multithreading and Low-Level Optimizations:
  • Low-level C++ efficiency techniques
  • C++ multithreading optimizations
  • AI LLM inference backend speedups
  • Low latency data structures
  • Multithreading optimizations
  • General C++ optimizations

Get your copy from Amazon: C++ Ultra-Low Latency