<commit_before>#include <cstdint>
#include <chrono>
#include <thread>
#include <functional>
#include <random>
#include <iostream>


#define INTERVAL_US_MIN 100
#define INTERVAL_US_MAX 500
#define COUNT_REPEAT    1000

const auto interval_min = std::chrono::microseconds(INTERVAL_US_MIN);
const auto interval_max = std::chrono::microseconds(INTERVAL_US_MAX);

//! @brief call do_something for repeat_count iterations.
void
doItRepeatedly(std::function<void(std::chrono::microseconds)> doIt,
               uint32_t repeat_count) {
    std::random_device seedGenerator;
    std::mt19937 gen(seedGenerator());
    std::uniform_int_distribution<> distribution(INTERVAL_US_MIN,
                                                 INTERVAL_US_MAX);

    std::chrono::microseconds jitter = std::chrono::microseconds(distribution(gen));

    for (uint32_t itr = 0; itr < repeat_count; ++itr) {
        auto start = std::chrono::steady_clock::now();
        doIt(jitter);
        auto end = std::chrono::steady_clock::now();
        auto elapsedTime = end - start;

        jitter = std::chrono::microseconds(distribution(gen));
        auto timeToWait = jitter - elapsedTime;
        if (timeToWait > std::chrono::microseconds::zero()) {
            std::this_thread::sleep_for(timeToWait);
        }
    }
}

class Jitters {
    std::vector<std::chrono::microseconds> jitters_;
    std::chrono::microseconds smallest_;
    std::chrono::microseconds largest_;

public:
    Jitters()
        : smallest_(std::chrono::microseconds::max())
        , largest_(std::chrono::microseconds::min()) {
    }

    void
    insert(std::chrono::microseconds j) {
        jitters_.push_back(j);

        if (j < smallest_) {
            smallest_ = j;
        }

        if (j > largest_) {
            largest_ = j;
        }
    }

    std::chrono::microseconds::rep
    average() {
        std::chrono::microseconds result(0);
        for (auto j : jitters_) {
            result = result + j;
        }

        result /= jitters_.size();

        return result.count();
    }

    std::chrono::microseconds::rep
    largest() {
        return largest_.count();
    }

    std::chrono::microseconds::rep
    smallest() {
        return smallest_.count();
    }

    std::chrono::microseconds::rep
    median() {
        return jitters_[jitters_.size() / 2].count();
    }
};


void main() {
    Jitters jitters;

    doItRepeatedly(std::bind(&Jitters::insert, &jitters, std::placeholders::_1), COUNT_REPEAT);

    std::cout << "Smallest jitter is: " << jitters.smallest() << std::endl;
    std::cout << "Largest jitter is:  " << jitters.largest() << std::endl;
    std::cout << "Average jitter is:  " << jitters.average() << std::endl;
    std::cout << "Median jitter is:   " << jitters.median() << std::endl;
}<commit_msg>wondering why expected and actual interations in test 2 don't match<commit_after>#include <cstdint>
#include <chrono>
#include <thread>
#include <future>
#include <functional>
#include <random>
#include <iostream>
#include <vector>
#include <algorithm>


using microsec = std::chrono::microseconds;
using millisec = std::chrono::milliseconds;
using nanosec = std::chrono::nanoseconds;
using resolution = nanosec;
using my_clock = std::chrono::steady_clock;

#define INTERVAL_PERIOD         resolution(20000000)
#define JITTER_MIN              0
#define JITTER_MAX              100
#define ITERATION_MAX           100
#define RUNTIME_LIMIT    resolution(4000000000)


template <int IntervalMin, int IntervalMax>
class PeriodicTimer {
private:
    volatile bool is_running_ = false;
    std::future<int> pending_;
    my_clock::time_point start_;
    my_clock::time_point end_;

    //! @brief call doIt until stop() is called, and return the number of
    // iterations for which doIt was called.
    int doItTimed(std::function<void(resolution)> doIt) {
        int result = 0;
        std::random_device seedGenerator;
        std::mt19937 gen(seedGenerator());
        std::uniform_int_distribution<> distribution(IntervalMin,
                                                     IntervalMax);
        resolution jitterNext = resolution(distribution(gen));
        resolution jitter;
        start_ = my_clock::now();
        my_clock::time_point start{start_};
        my_clock::time_point startNext{start};

        while (is_running_) {
            start = my_clock::now();
            my_clock::duration wakeupError = start - startNext;
            jitter = jitterNext;

            // Delay the function call for a small random amount of time.
            std::this_thread::sleep_for(jitter);
            doIt(jitter);
            ++result;

            // Get a new jitter for the next iteration
            jitterNext = resolution(distribution(gen));

            // Calculate the next time we want to iterate
            startNext = start + INTERVAL_PERIOD;

            // Wait for the next period start time
            std::this_thread::sleep_until(startNext);
        }
        end_ = my_clock::now();
        return result;
    }

public:
    //! @brief call doIt for repeat_count iterations. 
    // A random delay (jitter) is calculated for each call to doIt. If doIt
    // runs for less than the delay, doItCount will wait for the remaining time
    // before the next interval. If doIt takes more time than the delay, the
    // next iteration takes place immediately. This way, doIt is called no more
    // often than
    void doItCount(std::function<void(resolution)> doIt,
                        uint32_t repeat_count) {
        std::random_device seedGenerator;
        std::mt19937 gen(seedGenerator());
        std::uniform_int_distribution<> distribution(IntervalMin,
                                                     IntervalMax);

        resolution jitterNext = resolution(distribution(gen));
        resolution jitter;
        start_ = my_clock::now();
        my_clock::time_point start{start_};
        my_clock::time_point startNext{start};

        uint32_t itr = 0;
        while (itr < repeat_count) {
            auto start = my_clock::now();
            jitter = jitterNext;

            // Delay the function call for a small random amount of time.
            std::this_thread::sleep_for(jitter);
            doIt(jitter);
            ++itr;

            // Get a new jitter for the next iteration
            jitterNext = resolution(distribution(gen));

            // Calculate the next time we want to iterate
            startNext = start + INTERVAL_PERIOD;

            // Wait for the next period start time
            std::this_thread::sleep_until(startNext);
        }

        end_ = my_clock::now();
    }

    void start(std::function<void(resolution)> doIt) {
        is_running_ = true;
        // Run doItTimed on another thread, passing the "this" pointer and the
        // function doItTimed must run until stop() is executed.
        auto f = std::async(std::launch::async,
                            &PeriodicTimer::doItTimed,
                            this,
                            doIt);
        // Move the future to another variable so we don't wait for it here.
        pending_ = std::move(f);
    }

    int stop() {
        // Allow doItTimed to exit its while-loop
        is_running_ = false;
        // Wait until the thread is done
        std::future<int> f = std::move(pending_);

        // Return
        return f.get();
    }

    my_clock::duration runtime() const {
        return end_ - start_;
    }
};


class Jitters {
    std::vector<resolution> jitters_;
    resolution smallest_;
    resolution largest_;

public:
    Jitters()
        : smallest_(resolution::max())
        , largest_(resolution::min()) {
    }

    void
    insert(resolution j) {
        jitters_.push_back(j);

        if (j < smallest_) {
            smallest_ = j;
        }

        if (j > largest_) {
            largest_ = j;
        }
    }

    resolution::rep
    average() {
        resolution result(0);
        for (auto j : jitters_) {
            result = result + j;
        }

        result /= jitters_.size();

        return result.count();
    }

    resolution::rep
    largest() {
        return largest_.count();
    }

    resolution::rep
    smallest() {
        return smallest_.count();
    }

    resolution::rep
    median() {
        std::sort(jitters_.begin(), jitters_.end());
        return jitters_[jitters_.size() / 2].count();
    }
};


void main() {
    Jitters jitter1;
    const resolution jitterMin = resolution(JITTER_MIN);
    const resolution jitterMax = resolution(JITTER_MAX);
    const resolution repeatInterval = INTERVAL_PERIOD;
    PeriodicTimer<JITTER_MIN, JITTER_MAX> timer;

    std::cout << "The resolution of the high-resolution clock is: "
        << (static_cast<double>(std::chrono::high_resolution_clock::period::num)
            / std::chrono::high_resolution_clock::period::den) << " sec"
        << std::endl;
    std::cout << "The resolution of the steady clock is:          "
        << (static_cast<double>(std::chrono::steady_clock::period::num)
            / std::chrono::steady_clock::period::den)
        << " sec" << std::endl;
    std::cout << "The resolution of the system clock is:          "
        << (static_cast<double>(std::chrono::system_clock::period::num)
            / std::chrono::system_clock::period::den)
        << " sec" << std::endl << std::endl;

    std::cout << "Jitter Tests." << std::endl
        << "  Interval:   "
        << std::chrono::duration_cast<millisec>(repeatInterval).count()
        << " ms" << std::endl
        << "  Min Jitter: " << jitterMin.count() << " ns" << std::endl
        << "  Max Jitter: " << jitterMax.count() << " ns" << std::endl << std::endl;

    /*** Iteration Test ***/
    std::cout << "Jitter test 1. Iterations: " << ITERATION_MAX << std::endl;
    // Now returns a std::chrono::time_point for the steady_clock. The next
    // three variables are equivalent definitions of the same type.
    auto start = my_clock::now();
    my_clock::time_point start_steady = start;
    std::chrono::time_point<my_clock> start_time_point = start;

    timer.doItCount(std::bind(&Jitters::insert, &jitter1, std::placeholders::_1), ITERATION_MAX);
    auto end = my_clock::now();

    // The elapsed time is a std::chrono::time_point
    auto elapsedTime = end - start;

    std::cout << "Iterations            " << ITERATION_MAX << std::endl;
    std::cout << "Expected elapsed time "
        << ITERATION_MAX * std::chrono::duration_cast<millisec>(repeatInterval).count()
        << " ms" << std::endl;
    std::cout << "Actual elapsed time   "
        << std::chrono::duration_cast<millisec>(elapsedTime).count()
        << " ms" << std::endl;
    std::cout << "Duration              "
        << std::chrono::duration_cast<millisec>(timer.runtime()).count()
        << " ms" << std::endl;
    std::cout << "Smallest jitter is    " << jitter1.smallest() << " ns" << std::endl;
    std::cout << "Largest jitter is     " << jitter1.largest()  << " ns" << std::endl;
    std::cout << "Average jitter is     " << jitter1.average()  << " ns" << std::endl;
    std::cout << "Median jitter is      " << jitter1.median()   << " ns" << std::endl;

    std::cout << std::endl;

    /*** Timed Test ***/
    Jitters jitter2;
    const resolution iterationTimeLimit = RUNTIME_LIMIT;
    std::cout << "Jitter test 2. Timed : "
        << std::chrono::duration_cast<millisec>(iterationTimeLimit).count() << " ms" << std::endl;

    start = my_clock::now();
    timer.start(std::bind(&Jitters::insert, &jitter2, std::placeholders::_1));
    std::this_thread::sleep_for(iterationTimeLimit);
    int iterations = timer.stop();
    end = std::chrono::steady_clock::now();
    elapsedTime = end - start;

    std::cout << "Expected iterations " << iterationTimeLimit / repeatInterval
        << std::endl;
    std::cout << "Actual iterations   " << iterations << std::endl;
    std::cout << "Elapsed time        "
        << std::chrono::duration_cast<millisec>(elapsedTime).count()
        << " ms" << std::endl;
    std::cout << "Duration            "
        << std::chrono::duration_cast<millisec>(timer.runtime()).count()
        << " ms" << std::endl;
    std::cout << "Smallest jitter is  " << jitter2.smallest() << " ns" << std::endl;
    std::cout << "Largest jitter is   " << jitter2.largest()  << " ns" << std::endl;
    std::cout << "Average jitter is   " << jitter2.average()  << " ns" << std::endl;
    std::cout << "Median jitter is:   " << jitter2.median()   << " ns" << std::endl;
}

{'fraction_non_alphanumeric': 0.13679020200413552, 'fraction_numerical': 0.0066009225385716555, 'mean_word_length': 2.5422535211267605, 'pattern_counts': {'":': 0, '<': 264, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6220675', 'n_tokens_mistral': 3916, 'n_tokens_neox': 3735, 'n_words': 869}