folly/folly/chrono/Hardware.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <folly/Portability.h>

#include <chrono>
#include <cstdint>

//  Description of and implementation of sequences for precise measurement:
//    https://github.com/abseil/abseil-cpp/blob/20240116.2/absl/random/internal/nanobenchmark.cc#L164-L277

#if defined(_MSC_VER) && !defined(__clang__) && \
    (defined(_M_IX86) || defined(_M_X64))
extern "C" std::uint64_t __rdtsc();
extern "C" std::uint64_t __rdtscp(unsigned int*);
extern "C" void _ReadWriteBarrier();
extern "C" void _mm_lfence();
#pragma intrinsic(__rdtsc)
#pragma intrinsic(__rdtscp)
#pragma intrinsic(_ReadWriteBarrier)
#pragma intrinsic(_mm_lfence)
#endif

namespace folly {

inline std::uint64_t hardware_timestamp() {}

/// hardware_timestamp_measurement_start
/// hardware_timestamp_measurement_stop
///
/// Suitable for beginning precise measurement of a region of code.
///
/// Prevents the compiler from reordering instructions across the call. This is
/// in contrast with hardware_timestamp(), which may not prevent the compiler
/// from reordering instructions across the call.
///
/// Prevents the processor from pipelining the call with loads. This is in
/// contrast with hardware_timestamp(), which allows the processor to pipeline
/// the call with surrounding loads.
///
/// Does not prevent instruction pipelines from continuing execution across the
/// call. For example, does not prevent a store issued before the call from
/// continuing execution (becoming globally visible) across the call. This means
/// that this form may not be suitable for certain measurement use-cases which
/// would require such prevention. However, this would be suitable for typical
/// measurement use-cases which do not specifically need to measure background
/// work such as store execution.
std::uint64_t hardware_timestamp_measurement_start() noexcept;
std::uint64_t hardware_timestamp_measurement_stop() noexcept;

inline std::uint64_t hardware_timestamp_measurement_start() noexcept {}

inline std::uint64_t hardware_timestamp_measurement_stop() noexcept {}

} // namespace folly