乐于分享
好东西不私藏

TensorRT-LLM 0.5.0 源码之二十

TensorRT-LLM 0.5.0 源码之二十

tensorrt_llm/common

file(GLOB SRCS *.cpp)
file(GLOB CU_SRCS *.cu)

add_library(common_src OBJECT ${SRCS} ${CU_SRCS})
set_property(TARGET common_src PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET common_src PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON)

assert.h

namespace tensorrt_llm::common
{
[[noreturn]]inline void throwRuntimeError(const char* const file, int const line, std::string const& info = "")
{
    throw
 TllmException(file, line, fmtstr("[TensorRT-LLM][ERROR] Assertion failed: %s", info.c_str()));
}

} // namespace tensorrt_llm::common

C++ 中的 [[noreturn]] 属性用于明确告知编译器和代码的阅读者:被标记的函数在任何情况下都不会返回到它的调用点。这意味着一旦程序执行进入这个函数,就不会再回到调用它的地方继续执行后续代码。

为了让你快速把握其核心,下表对比了 [[noreturn]] 函数与普通 void 函数的本质区别:

特性
普通 void 函数
[[noreturn]]
 函数
控制流
执行完毕后返回调用者
不返回
调用者,流程中断
典型行为
正常执行逻辑
终止程序、抛出异常、无限循环
编译器视角
需要为函数返回生成代码
知道后续代码不可达,可进行优化

主要用途与优势

使用 [[noreturn]] 属性主要能带来以下好处:

  1. 1. 编译器优化:这是最直接的作用。编译器得知函数不会返回后,可以执行特定优化。例如,它会识别出在该函数调用之后的所有代码都是死代码,并可能在编译时将其移除或发出警告。同时,对于不会返回的函数,编译器可能会省略一些为函数返回所做的准备(例如不必要的栈帧清理代码),从而优化生成的目标代码。
  2. 2. 提升代码质量与可读性:这个属性作为一种机器可读的文档,清晰地表明了函数的设计意图——它将中断正常的控制流。这极大地提高了代码的可读性和可维护性,让其他开发者或未来的你一眼就能明白该函数的行为影响。
  3. 3. 增强错误检查:编译器可以利用此属性提供更智能的警告。例如,如果一个被标记为 [[noreturn]] 的函数内部竟然存在可以执行到函数末尾并隐式返回的路径,或者在其后书写了明显不会执行的代码,编译器可能会发出警告,帮助你发现潜在的逻辑错误。

典型适用场景

你通常会在以下类型的函数上使用 [[noreturn]] 属性:

  • • 终止程序的函数:例如,封装了 std::exit()std::abort() 的错误处理或致命退出函数。
  • • 抛出异常的函数:那些其唯一目的就是抛出特定异常的函数。
  • • 无限循环:例如,某些任务调度器或服务器的主循环,它们设计上就是永不退出的。

重要注意事项与陷阱

使用 [[noreturn]] 时必须谨慎,否则会导致未定义行为:

  • • 核心规则:函数绝不能返回:这是最重要的原则。如果你给一个函数标记了 [[noreturn]],就必须确保它在所有执行路径上都绝对不会返回到调用者。如果某个路径下函数执行完毕并返回了,程序将进入未定义行为 的状态。在Debug模式下程序可能看似正常,但在Release模式下开启编译器优化后,由于编译器可能已经移除了返回后的处理逻辑,极易导致程序崩溃或产生不可预测的结果。
  • • 不要滥用:这个属性并非用于提升性能的主要手段,其优化效果通常是局部的。只有在函数行为确实符合“不返回”的语义时才应使用。
  • • 与 void 的区别:再次强调,void 表示函数不返回,但执行后会返回调用处。[[noreturn]] 表示函数不返回控制流,执行后流程中断。

代码示例

#include <iostream>
#include <cstdlib> // 用于 std::exit

#include <stdexcept> // 用于 std::runtime_error


// 场景1: 终止程序

[[noreturn]]void fatalError(const std::string& message){
    std::cerr << "Fatal Error: " << message << std::endl;
    std::exit(EXIT_FAILURE); // 程序终止,不会返回
}

// 场景2: 抛出异常

[[noreturn]]void throwRuntimeError(const std::string& msg){
    throw
 std::runtime_error(msg); // 抛出异常,控制流不会返回
}

// 场景3: 无限循环 (例如某些嵌入式系统的主循环)

[[noreturn]]void mainLoop(){
    while
 (true) {
        // ... 执行周期性任务

    }
}

// 错误示例:此函数有条件返回,标记[[noreturn]]会导致未定义行为!

[[noreturn]]void problematicFunction(bool shouldExit){
    if
 (shouldExit) {
        std::exit(0);
    }
    // 如果 shouldExit 为 false,函数会执行到这里并返回,违反 [[noreturn]] 约定!

} // 危险!

int main()
{
    // fatalError("Disk full"); // 调用后程序终止,后面的代码不会执行

    // std::cout << "This will never be printed.\n";


    throwRuntimeError
("Something went wrong");
    // 抛出异常后,控制流也不会回到这里


    return
 0;
}

总结

总而言之,[[noreturn]] 是一个有用的属性,但带有“破坏性”。它通过告知编译器控制流信息来辅助优化和错误检测,并作为代码文档。使用时务必严格遵守其核心约定:被标记的函数必须真正永不返回,否则会引发未定义行为。


#if defined(_WIN32)
#define TLLM_LIKELY(x) (__assume((x) == 1), (x))

#else

#define TLLM_LIKELY(x) __builtin_expect((x), 1)

#endif

__builtin_expect((x), 1) 是 GCC 编译器提供的一个内置函数(其他如 Clang 也支持),其主要作用是为编译器提供分支预测信息,提示编译器表达式 x 的结果非常可能为真(即值等于1),从而帮助编译器优化代码,提升程序运行效率。

为了让您快速掌握其核心要点,下表总结了关键信息:

特性
说明
函数原型long __builtin_expect (long exp, long c)
本语句含义
期望(预测)表达式 x 的值很可能为真(即等于1)
返回值
返回第一个参数 exp(即 x)的值本身
核心目的
辅助编译器进行静态分支预测,优化指令顺序,减少CPU流水线停顿
常见封装
通常被封装为 likely(x) 宏

工作原理与优化效应

现代CPU普遍采用指令流水线预取机制来提高效率。当处理器遇到条件分支(如 if 语句)时,它需要“猜测”接下来会执行哪个分支(称为分支预测),并提前将相应指令加载到高速缓存中。如果预测错误,已经预取和部分执行的指令就需要被丢弃,然后重新加载正确分支的指令,这个过程会导致流水线清空,造成性能损失。

__builtin_expect((x), 1) 的作用就是向编译器传递一个明确的提示:“x 为真的可能性极大”。编译器在生成汇编代码时,会将可能性更高的代码块(if 块)紧挨着条件判断指令之后排列,而将可能性较小的代码块(else 块)放在相对较远的位置,通常需要通过跳转指令才能到达。

这样做的好处是:

  • • 提高缓存局部性:最常执行的指令在内存中连续分布,更有可能已被预取到高速缓存中,减少了CPU等待数据的时间。
  • • 减少分支预测错误惩罚:由于代码布局符合预期执行流程,CPU的分支预测器做出正确预测的概率更高,从而显著减少了因预测错误导致的流水线清空和刷新。

实际应用方式

在实际编程中,__builtin_expect 通常不会被直接使用,而是被定义成宏,以提高代码的可读性。最常见的宏是 likely 和 unlikely

#define likely(x)   __builtin_expect(!!(x), 1)   // 表示x很可能为真
#define unlikely(x) __builtin_expect(!!(x), 0)   // 表示x很可能为假

这里的 !!(x) 是一个小技巧,它的作用是将参数 x 强制转换为逻辑上的布尔值(0或1)。无论 x 是什么类型或值,!!(x) 的结果都严格等于0(假)或1(真)。

一个典型的使用场景是在错误检查或异常处理中,因为这些情况通常很少发生。

// 检查指针ptr是否有效,正常情况下大概率是有效的
if
 (likely(ptr != nullptr)) {
    // 编译器会优化代码,优先保证这个主流程的指令顺序紧凑、连续

    do_something_with
(ptr);
} else {
    // 错误处理路径:概率很小,编译器可能会将其放在远离主流程的位置

    handle_error
();
}

// 检查一个非常罕见的错误条件

if
 (unlikely(some_rare_error_condition)) {
    // 这个小概率分支的代码会被特殊安排

    log_error
();
    return
 ERROR_CODE;
}

重要注意事项

  1. 1. 不要滥用:只有在某个分支的执行概率具有非常明显的偏向性(例如,99% vs 1%)时,使用 __builtin_expect 才能带来可观的性能提升。如果分支概率接近50/50,使用它可能收效甚微,甚至可能因为错误的提示而略微降低性能。GCC官方文档也建议,相比于程序员的主观预测,使用 -fprofile-arcs 选项通过实际运行来分析分支概率是更科学的方法。
  2. 2. 不影响逻辑:需要明确的是,if (likely(x)) 在语法上完全等价于 if (x)。这个宏只影响编译优化,不会改变程序的逻辑。它的返回值就是第一个参数 x 本身。
  3. 3. 编译器兼容性:这是GCC的扩展功能。在编写可移植代码时,通常需要检查编译器类型,对于不支持该特性的编译器,需要提供回退方案。
    #if defined(__GNUC__) || defined(__clang__)
    #define LIKELY(x)   __builtin_expect(!!(x), 1)

    #define UNLIKELY(x) __builtin_expect(!!(x), 0)

    #else

    #define LIKELY(x)   (x) // 对于其他编译器,直接定义为原表达式

    #define UNLIKELY(x) (x)

    #endif

总结

总而言之,__builtin_expect((x), 1) 是一个用于性能微调的低级工具。它通过向编译器提供明确的分支概率提示,帮助优化代码布局,从而在现代处理器上获得更好的执行效率。在实际应用中,建议通过 likely/unlikely 宏来使用它,并严格用于那些执行概率有明显偏差的关键路径上。


#define TLLM_CHECK(val)                                                                                                \
    do                                                                                                                 \
    {                                                                                                                  \
        TLLM_LIKELY(static_cast<bool>(val)) ? ((void) 0)                                                               \
                                            : tensorrt_llm::common::throwRuntimeError(__FILE__, __LINE__, #val);       \
    } while (0)


#define TLLM_CHECK_WITH_INFO(val, info)                                                                                \
    do                                                                                                                 \
    {                                                                                                                  \
        TLLM_LIKELY(static_cast<bool>(val)) ? ((void) 0)                                                               \
                                            : tensorrt_llm::common::throwRuntimeError(__FILE__, __LINE__, info);       \
    } while (0)


#define TLLM_THROW(...)                                                                                                \
    do                                                                                                                 \
    {                                                                                                                  \
        throw NEW_TLLM_EXCEPTION(__VA_ARGS__);                                                                         \
    } while (0)


#define TLLM_WRAP(ex)                                                                                                  \
    NEW_TLLM_EXCEPTION("%s: %s", tensorrt_llm::common::TllmException::demangle(typeid(ex).name()).c_str(), ex.what())

在C和C++编程中,((void)0) 是一个经典的技巧,主要用于在需要表达式的地方提供一个明确不执行任何操作(no-op)且不产生任何值的占位符。为了让你快速抓住要点,我先用一个表格来总结它的核心用途和原理。

特性
说明
核心作用
充当一个明确的、不产生任何效果的表达式(空操作,no-op)
关键原理
将字面值 0 强制转换为 void 类型,表示该表达式的值“不存在”且不应被使用
主要优势1消除编译器警告
:避免类似“expression has no effect”的警告
主要优势2防止误用
:若尝试使用该表达式的值(如赋值),编译器会报错,增强了类型安全
经典场景
宏定义中的占位符,尤其是在条件编译中(如assert宏或调试宏)

详细说明与应用场景

工作原理

这个技巧的核心在于类型转换。字面值 0 本身是一个 int 类型的表达式。当你使用 (void)0 时,你执行了一次显式的类型转换,将 0 这个值强制转换为 void 类型。在C/C++标准中,void 类型表示“无类型”,一个 void 类型的表达式不表示任何实际的值,因此它不能被用于需要值的上下文中(比如赋值给变量或参与运算)。同时,计算这个表达式本身不产生任何实际的可执行代码(即无操作)。

常见应用场景

  1. 1. 宏定义中的安全占位符
    这是 ((void)0) 最经典和常见的用法。在编写宏时,尤其是在条件编译中,经常需要定义一个在特定情况下(如发布模式)什么都不做的宏。直接使用一个空的 #define 可能在语法上不完整,而使用 ((void)0) 则能提供一个符合语法、功能正确且安全的空语句。
    #ifdef DEBUG
      #define DEBUG_PRINT(x) printf(x)

    #else

      #define DEBUG_PRINT(x) ((void)0)  // 在非调试模式下,该宏展开后什么都不做

    #endif

    在上面的例子中,当 DEBUG 未定义时,代码中所有 DEBUG_PRINT("message") 都会被替换为 ((void)0)。这样做的好处是,即使你在 if 语句等后面不加分号直接调用这个宏,比如 DEBUG_PRINT("test"),展开后是 ((void)0);,这依然是一个合法的空语句,不会导致语法错误。

  2. 2. 断言宏的实现
    在许多库的断言宏实现中,也能看到 (void)0 的身影。它通常被用在断言成功的分支上。
    #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

    在这里,如果表达式 expr 为真,则断言成功,执行 (void)0(无操作);如果为假,则调用错误处理函数 assert_failed

注意事项与替代方案

  • • 与 void* 的区别:务必分清 (void)0 和 ((void*)0)。前者产生一个 void 类型的值表达式,用于表示“无值”。后者产生一个 void* 类型的空指针常量,通常用来定义 NULL,表示指针不指向任何对象。
  • • C++中的 static_cast:在C++中,为了更符合现代类型转换风格,可以使用 static_cast<void>(0) 来达到完全相同的效果,它们在功能上是等价的。
  • • 编译器的特殊支持:某些编译器提供了类似功能的内在函数,例如微软VC++的 __noop。但 ((void)0) 因其标准性和可移植性而被广泛采用。

总而言之,((void)0) 是一个巧妙运用C/C++类型系统来实现安全、无副作用的空表达式的最佳实践。它在宏定义、条件编译等场景中尤为重要,是编写健壮和可移植代码的一个有用工具。


C++ 中的 typeid 操作符是运行时类型识别(RTTI)机制的核心组成部分,它允许程序在运行时查询变量、对象或类型的详细信息。下面这个表格汇总了它的核心特性,帮助你快速把握要点。

特性
说明
主要功能
获取表达式或类型的运行时类型信息
返回值类型
对 const std::type_info 对象的引用
关键方法.name()
 (返回类型名称), 比较操作 (==!=)
多态类型
返回对象的动态(实际)类型(需含虚函数)
非多态类型
返回表达式的静态(声明)类型
使用头文件#include <typeinfo>

基本用法与注意事项

使用 typeid 需要包含 <typeinfo> 头文件。它的返回值是一个 const std::type_info&,你可以利用这个对象进行类型比较或获取类型名称。

#include <iostream>
#include <typeinfo>


int main()
{
    int
 i = 0;
    const
 std::type_info& ti = typeid(i);
    std::cout << "Type of i: " << ti.name() << std::endl; // 输出类型名称,如 'i' 表示 int

    // 直接比较类型

    if
 (typeid(i) == typeid(int)) {
        std::cout << "i is definitely an int." << std::endl;
    }
    return
 0;
}

需要注意,std::type_info::name() 返回的类型名称字符串是编译器相关的,可能可读性不强(例如,GCC 中 int 可能显示为 "i")。如果需要更友好的显示,可以考虑使用像 abi::__cxa_demangle (GCC/Clang) 这样的解译函数。

理解静态类型与动态类型

typeid 最核心的行为取决于操作数是否为多态类型(即至少包含一个虚函数的类)。

  • • 非多态类型(静态类型):对于没有虚函数的类型(包括基本数据类型,如 intdouble),或者指向非多态类型的指针本身,typeid 在编译时即可确定结果,返回的是表达式或变量的静态类型(声明类型)。
    class BaseWithoutVirtual {};
    class
     Derived : public BaseWithoutVirtual {};

    Derived d;
    BaseWithoutVirtual* bp = &d;
    std::cout << typeid(*bp).name() << std::endl;
    // 输出 BaseWithoutVirtual 的类型名,因为基类没有虚函数,识别的是静态类型
  • • 多态类型(动态类型):当对多态类型的对象、引用或指针解引用(如 *ptr)使用时,typeid 会在运行时确定其动态类型(实际指向的对象的类型)。
    class Base {
    public
    :
        virtual
     ~Base() {} // 至少有一个虚函数,使Base成为多态类型
    };
    class
     Derived : public Base {};

    Derived d;
    Base* bp = &d; // 基类指针指向派生类对象
    std::cout << typeid(*bp).name() << std::endl;
    // 输出 Derived 的类型名,因为基类有虚函数,识别的是动态类型

重要陷阱与安全用法

  1. 1. 空指针解引用:对空指针进行解引用操作以获取类型信息会导致 std::bad_typeid 异常。
    Base* bp = nullptr;
    try
     {
        // 错误!对空指针bp解引用

        std::cout << typeid(*bp).name() << std::endl; 
    } catch (const std::bad_typeid& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }

    安全的做法是首先检查指针是否有效,或者直接对指针本身使用 typeid(但这会返回指针类型,而不是所指对象的类型)。

  2. 2. 类型比较的局限性typeid 比较的是类型的精确匹配。基类和派生类被认为是不同的类型。typeid 会忽略顶层的 const 和 volatile 限定符,即 typeid(const int) == typeid(int) 结果为 true

实践建议与替代方案

  • • 谨慎使用:RTTI 会带来一定的运行时开销。如果可以通过虚函数等设计在编译时确定行为,通常是更好的选择。
  • • 类型名称的可移植性:不要依赖 name() 返回字符串的格式,因为它因编译器而异。
  • • 考虑替代方案:在模板编程或需要编译期类型判断时,可以考虑使用 <type_traits> 等现代 C++ 特性,它们通常更高效。

总结

typeid 操作符是 C++ RTTI 的关键工具,主要用于在运行时确定类型信息,特别是在涉及多态类型的场景下。使用时需牢记其静态类型与动态类型的区别,并注意空指针安全问题。虽然在某些调试或特定框架中很有用,但在追求高性能的代码中应权衡其开销。

Memory Allocator

enum class ReallocType
{
    INCREASE,
    REUSE,
    DECREASE,
};
class IAllocator
{
public
:
    virtual
 ~IAllocator() = default;

    // no copying

    IAllocator
(const IAllocator&) = delete;
    IAllocator& operator=(const IAllocator&) = delete;

    template
 <typename T>
    [[nodiscard]] T* reMalloc(T* ptr, size_t sizeBytes, const bool setZero = true)
{
        TLLM_LOG_DEBUG
(__PRETTY_FUNCTION__);
        // TODO martinma: why do we need this size extension?

        auto
 const sizeAligned = ((sizeBytes + 31) / 32) * 32; // make the buffer align with 32 bytes
        if
 (contains(ptr))
        {
            auto
 const realloc = reallocType(ptr, sizeAligned);
            if
 (realloc == ReallocType::INCREASE)
            {
                TLLM_LOG_DEBUG
("ReMalloc the buffer %p since it is too small.", ptr);
                free
(&ptr);
                return
 reinterpret_cast<T*>(malloc(sizeAligned, setZero));
            }
            else
 if (realloc == ReallocType::DECREASE)
            {
                TLLM_LOG_DEBUG
("ReMalloc the buffer %p to release unused memory to memory pools.", ptr);
                free
(&ptr);
                return
 reinterpret_cast<T*>(malloc(sizeAligned, setZero));
            }
            else

            {
                assert
(realloc == ReallocType::REUSE);
                TLLM_LOG_DEBUG
("Reuse original buffer %p with size %d and do nothing for reMalloc.", ptr, sizeAligned);
                if
 (setZero)
                {
                    memSet
(ptr, 0, sizeAligned);
                }
                return
 ptr;
            }
        }
        else

        {
            TLLM_LOG_DEBUG
("Cannot find buffer %p, mallocing new one.", ptr);
            return
 reinterpret_cast<T*>(malloc(sizeAligned, setZero));
        }
    }

virtual void free(void** ptr)
= 0;

    template
 <typename T>
void free(T** ptr)
{
        free
(reinterpret_cast<void**>(ptr));
    }

protected
:
    IAllocator
() = default;

virtual void* malloc(std::size_t size, bool setZero)
= 0;
virtual void memSet(void* ptr, int val, std::size_t size)
= 0;

virtual bool contains(void const* ptr) const
= 0;
virtual ReallocType reallocType(void const* ptr, size_t size) const
= 0;
};

在 C 中,`[[nodiscard]]` 是一个属性标识符,用于告诉编译器和代码的阅读者:某个函数的返回值**非常重要,不应该被忽略**。自 C17 引入以来,它成为提升代码安全性和健壮性的重要工具。

核心含义与基本用法

[[nodiscard]] 的核心含义是“不应舍弃”。当调用被它标记的函数时,如果其返回值没有被有意识地处理(例如,没有赋值给变量,也没有用于条件判断),编译器会发出警告。

它的基本语法如下:

  • • 在 C++17 中:[[nodiscard]]
  • • 在 C++20 中进行了扩展,允许附带说明信息:[[nodiscard("提示字符串")]]

下面是一个简单的例子:

// 标记一个函数的返回值为 nodiscard
[[nodiscard]]int importantFunction(){
    return
 42;
}

int main()
{
    importantFunction
(); // ⚠️ 编译器警告:返回值被忽略!
    int
 value = importantFunction(); // ✅ 正确:返回值被保存
    static_cast
<void>(importantFunction()); // ✅ 正确:显式丢弃,通常不会警告
    return
 0;
}

在 C++20 中,你可以提供更清晰的提示:

[[nodiscard("请检查操作是否成功")]]bool performOperation(){
    return
 true;
}

应用范围与场景

[[nodiscard]] 不仅可以标记函数,还可以标记类、枚举等,应用场景广泛。

应用对象
说明与示例
使用场景举例
函数返回值
直接标记函数,确保其返回值被使用。
错误检查、重要的计算结果。
类/结构体
将整个类标记为 [[nodiscard]],则该类的任何构造函数返回的临时对象都不应被忽略。
工厂函数返回的资源管理对象(如文件句柄、数据库连接),忽略它可能导致资源立即释放。
枚举类型
标记特定的枚举类,其返回值也不应被忽略。
强类型的错误码枚举,确保调用方检查操作状态。
构造函数
可以单独标记类的构造函数。
确保某些必须被接收的临时对象不被忽略。

为什么要使用 [[nodiscard]]

使用 [[nodiscard]] 主要目的是在编译期捕获因疏忽导致的潜在错误,从而:

  • • 防止资源泄漏:例如,忽略一个返回 std::unique_ptr 的工厂函数的结果,会导致分配的资源立刻被释放。
  • • 强制错误检查:确保函数返回的错误码或成功状态得到检查,避免程序在错误状态下继续运行。
  • • 保证计算结果被使用:避免无意义的函数调用,提高代码质量。

需要注意的细节与陷阱

  1. 1. 对返回引用或指针无效:如果函数返回的是被标记为 [[nodiscard]] 的类的引用或指针,编译器通常不会发出警告。因为这种返回形式可能表示返回的是已存在的对象,而非需要接收的新资源。
  2. 2. 可以有意绕过:虽然 [[nodiscard]] 会发出警告,但开发者仍然可以通过将返回值赋值给变量或使用 std::ignore 来明确表示“我已知晓,并有意忽略”。这体现了 C++“相信程序员”的理念。
  3. 3. 谨慎用于作用域守卫(Scope Guard):如果一个函数返回一个作用域守卫对象(依靠其析构函数进行清理),标记 [[nodiscard]] 通常是正确且必要的。这可以防止守卫对象被立即销毁。但需注意,用户仍可能通过 std::ignore 等方式忽略它,导致清理操作未按预期执行。

编译器支持

主流编译器如 GCC (7+)、Clang (3.9+) 和 MSVC (2017 15.3+) 都提供了对 [[nodiscard]] 的支持。

[[nodiscard]] 是一个低开销、高效的工具,它能帮助你在编译阶段就发现许多因粗心导致的错误。在编写新的 API,尤其是涉及资源管理、错误状态返回的函数时,积极地使用它是一个非常好的习惯。

希望这些解释能帮助你更好地理解 [[nodiscard]]。如果你有特定的使用场景想讨论,我很乐意听听你的想法。


在C++中,__PRETTY_FUNCTION__ 是一个编译器扩展宏,主要用于调试和日志记录,它能提供当前函数的详细签名信息。

下面的表格快速对比了C++中几个常见的函数名宏/标识符:

名称
标准/扩展
输出信息示例
主要特点
__PRETTY_FUNCTION__
GCC/Clang 扩展
void MyClass::myFunction(int, double) const
提供最详细的函数签名,包括类名、参数类型列表、常量性等。
__FUNCSIG__
MSVC 扩展
void __cdecl MyClass::myFunction(int, double) const
功能类似__PRETTY_FUNCTION__,但用于Visual Studio编译器。
__func__
C++11 标准
myFunction
仅返回函数的朴素名称,不包含类名和参数信息,可移植性好。
__FUNCTION__
预标准扩展
myFunction
多数编译器中与__func__相同,为保证兼容性而存在。

💡 核心用途与示例

__PRETTY_FUNCTION__ 的核心价值在于,当你在一个函数内部使用它时,它会展开为一个包含函数完整签名的字符串。这对于以下场景特别有用:

  • • 调试程序:快速确认代码执行流进入了哪个特定的函数重载或模板实例。
  • • 日志记录:在日志中输出详细的函数调用信息,便于追踪问题。

例如,在下面的代码中:

#include <iostream>
class
 MyClass {
public
:
void myMethod(int x)
{
        std::cout << "__PRETTY_FUNCTION__: " << __PRETTY_FUNCTION__ << std::endl;
    }
};

int main()
{
    MyClass obj;
    obj.myMethod(10);
    return
 0;
}

运行后可能会输出:__PRETTY_FUNCTION__: void MyClass::myMethod(int)。这清晰地显示了函数所属的类、函数名和参数类型。

对于C++模板和重载函数,__PRETTY_FUNCTION__ 的优势更加明显,它能明确显示出模板参数的具体类型和函数签名,帮助区分不同的实例化版本或重载。

⚠️ 重要注意事项

  1. 1. 编译器依赖性__PRETTY_FUNCTION__ 并非C标准的一部分,是GCC和Clang等编译器的扩展。如果你需要编写跨编译器的代码,需要注意这一点。在Microsoft Visual C (MSVC) 中,等效的宏是 __FUNCSIG__
  2. 2. C++20 的现代替代方案:从C++20开始,标准库引入了 std::source_location。它提供了一个更标准、更可移植的方式来获取代码信息,包括函数名、文件名、行号等。
    #include <iostream>
    #include <source_location>


    void log(const std::source_location& loc = std::source_location::current())
    {
        std::cout << "Function: " << loc.function_name() << std::endl;
        std::cout << "File: " << loc.file_name() << " at line " << loc.line() << std::endl;
    }

    int main()
    {
        log
    (); // 会自动捕获main函数中调用位置的信息
    }

    在新项目中,如果目标是C++20或更高,并且需要跨平台兼容性,推荐优先考虑使用 std::source_location

总结

总而言之,__PRETTY_FUNCTION__ 是一个在GCC/Clang环境下非常实用的调试工具,它能提供丰富的函数签名信息。但在使用时,请留意其编译器特异性,并了解C++20提供了更现代化的替代方案 std::source_location


代码 auto const sizeAligned = ((sizeBytes + 31) / 32) * 32; 是一种常见的内存对齐编程技巧。它的核心目的是将原始数据大小 (sizeBytes) 向上舍入到最接近的 32 字节的整数倍,其带来的好处主要体现在性能和兼容性上。

下面的表格详细说明了这种对齐操作带来的主要好处、背后的原因以及典型应用场景。

好处
原理说明
应用场景/影响
提升CPU访问效率
现代CPU通常以固定大小的块(如64字节的缓存行)访问内存。如果数据块横跨两个缓存行,CPU可能需要两次内存访问才能读完全部数据,并进行数据拼接,这会增加额外开销。对齐到32字节有助于确保关键数据落在更少的缓存行内。
高频访问的数据结构、大型数组循环遍历。
满足指令集要求
某些特殊的CPU指令(如Intel的SSE、AVX等SIMD指令)要求操作的数据在内存中必须按特定边界(如16、32或64字节)对齐。未对齐的访问会直接导致程序崩溃(如SIGBUS信号)。
使用SIMD指令进行高性能并行计算(如图像处理、科学计算)。
优化缓存利用率
CPU缓存被划分为缓存行。当数据对齐后,它能够更紧凑地填充缓存行,减少缓存空间的浪费,从而提高缓存命中率。反之,未对齐的数据可能分散在多个缓存行中,导致缓存效率低下。
任何对性能敏感的应用,追求低缓存未命中率。
避免平台差异问题
在一些特定的硬件架构(如某些ARM或RISC处理器)上,访问非对齐的内存地址是完全不被允许的,会导致硬件异常或总线错误(Bus Error)。确保对齐可以增强代码的跨平台可移植性。
嵌入式系统、跨平台(x86/ARM)项目开发。

代码是如何实现对齐的?

这行代码 ((sizeBytes + 31) / 32) * 32 是一个经典的“向上取整”算法:

  • • sizeBytes + 31:首先,将原始大小加上一个比对齐边界(32)小1的值(31)。这相当于预先分配出可能需要的最大填充空间。
  • • / 32:然后,进行整数除法。整数除法会自动截断小数部分,结果相当于“向下取整”到32的倍数。
  • • * 32:最后,再乘以32,将“向下取整”的结果恢复为32的倍数,这样就实现了“向上取整”。

例如,如果 sizeBytes 是 50:

  • • (50 + 31) = 81
  • • 81 / 32 = 2 (整数除法)
  • • 2 * 32 = 64
    最终,对齐后的大小 sizeAligned 就是 64。

权衡与注意事项

虽然内存对齐好处很多,但它是一种典型的 “以空间换时间” 的策略。你可能会在成员之间和结构体末尾引入一些为对齐而存在的填充字节,从而增加总的内存占用。

在绝大多数对性能要求高的场景下(如游戏引擎、高频交易、科学计算),这种微小的空间开销换来的性能提升是非常值得的。但在内存极其受限的嵌入式环境中,可能需要谨慎权衡,甚至使用 #pragma pack 等指令减少填充。

总结

总而言之,将缓冲区对齐到32字节,主要是为了压榨CPU性能确保程序正确性。这是一个在系统编程和高性能计算中常用的重要优化手段。

参考文献

  • • https://github.com/NVIDIA/TensorRT-LLM/tree/release/0.5.0/cpp/tensorrt_llm/common
点个「赞」+「在看」❤️
让我们知道这份文字有温暖到你,也是我们持续创作的最大动力!
推荐
nano-vllm-voxcpm 架构
LLM推理优化的核心技术:深入理解KV缓存与分页注意力机制
HF 和 TRT-LLM multinomial 采样解码实现三
TensorRT-LLM 0.5.0 源码之十八
TensorRT-LLM 0.5.0 源码之十七
HF 和 TRT-LLM multinomial 采样解码实现二
TensorRT-LLM 0.5.0 源码之十六
flashinfer.sampling 实现二
TensorRT-LLM 0.5.0 源码之十四
Ruff:打造无错误、高可维护性Python代码的现代化代码检查工具
HF 和 TRT-LLM multinomial 采样解码实现一
入门MPI必看!一文搞懂分布式并行编程的核心基础
MPI Hello World 教程:从代码解析到运行实操
MPI 组与通讯器详解
什么是氛围编程(Vibe Coding)?
BS::thread_pool 一个快速、轻量级、现代且易于使用的线程池库
MiMo-V2-Flash技术报告
AI原生开发中的MCP与CLI对比
flashinfer.sampling 实现一
Qwen3-TTS 技术报告
Vibe Coding 氛围编程最佳实践
Paged Attention, IFB, and Request Scheduling
VoxCPM 模型结构
理解 VoxCPM 模型
Claude Code 源码泄露:伪造工具、挫败感正则、卧底模式及更多
Claude Code代码泄露事件-愚人节前的礼物
Multi-Head, Multi-Query, and Group-Query Attention
PagedAttention
什么是 Programmatic Dependent Launch
如何让AI听懂你的“话外音”?GOAT-SLM模型实现更懂情感的语言交互
Optimize Prompts
大模型部署必看:LLM 推理(Inference)优化 技术,适配高并发、低延迟场景
LLM Serving Benchmark Metrics
告别语音克隆烦恼:VoxCPM用Token-Free方案,打造真实会“思考”的AI语音
OpenCharacter: 利用大规模合成人物角色训练可定制化角色扮演语言模型
FlashAttention与PagedAttention详解:拯救GPU显存,让大模型飞起来的核心技术
Introducing CUDA UnBound (CUB)
Meta Prompting: A Guide to Automated Prompt Optimization
CUDA 中如何使用虚函数
DeepSpeed的ZeRO技术具体是如何实现显存优化的?
LM-as-a-judge:LLM评估指南
LLM Sequence Packing
深入了解SmoothQuant:大模型高效量化背后的数学原理
ART·E: How We Built an Email Research Agent That Beats o3
中文LLM指令微调动态机制
intro to GRPO an efficient policy optimization method
提升TTS语音合成效果:低质量数据清洗、增强与数据扩增
语音合成(TTS)分句生成拼接时的响度一致性问题:现状、成因与对策
TTS的CFM中的class-free指的是什么?
当扩散模型遇上流匹配:原来是一回事儿
语音合成中的“一对多”问题主流模型解决方案分析
Share Memory 的 Bank Conflict
告别高成本!TensorRT-LLM实战:如何将LLM推理速度提升数倍
使用LoRA对LLM进行微调的实用技巧
强化学习小白必看:PTX Loss 到底是个啥?
GPT-5 Prompt Migration and Improvement Using the New Optimizer
Hugging Face BPE Tokenizer 的资源文件
RULER: Relative Universal LLM-Elicited Rewards
SFT和RFT的区别
语音合成(TTS)中文自然度:问题、成因、解决方案
上下文工程如何实现
上下文工程(Context Engineering)
SFT 泛化新解读:强化学习 + 奖励修正,一文读懂
Evol-Instruct 竟能精准生成领域专属数据?实操技巧速看!
指令微调数据-少即是多
语音合成(TTS)跳跃与重复问题的解析:成因、机制及解决方案
大模型训练新思路:GEPA 靠 “反思” 赢过 RL,看完秒懂
DPO、PPO、GRPO的原理,区别与联系
OPENCSG 中文语料库:一系列高质量的中文数据集,用于语言模型训练
什么是 Classifier-Free Guidance?
Conditional Flow Matching : 连续标准流 Continuous Normalizing Flow
CFM 与 OT-CFM:条件流匹配与最优传输的碰撞
DPO损失实现
Conditional Flow Matching : 常微分方程ODE、欧拉方法和Neural ODE
当 Normalizing flow 遇上语音生成:AI 说话变 “真人” 的秘密在这里!
为什么说分布变换是 Normalizing flow 的「灵魂操作」?
从知识增长的角度提升RAG上下文的质量
手把手教你创建 evol-instruct 数据集!附完整流程~
社交类聊天的 Query 分析与应答策略
SFT 中指令选择和响应选择哪个更重要?
角色扮演大模型技术分享2-超拟人模型的困境
最新!SpeechLLM 综述:架构、能力、挑战与未来全揭秘
如何低成本生成高质量指令微调数据?
从数量到质量:通过自引导数据选择来提升语言模型性能以实现指令调优
Qwen 的训练数据是怎么做的?
如何低成本生成高质量指令微调数据?
掌握RAG:投入生产前要评估的8个场景
掌握RAG:如何评估RAG的LLM
掌握RAG:如何在部署后观察您的RAG
掌握RAG:如何选择嵌入模型
Semantic token和连续特征在SLLM下的对比
RLHF及其变体:进展和实际工程见解
什么是置信度?置信度模型怎么做?
晦涩难懂的 Flow matching!图形化理解
FSQ的原理与VQ-VAE的区别和联系
大模型并行训练的一些知识——极简版
RLHF 入门,高手勿进!
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-26 22:34:49 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/672871.html
  2. 运行时间 : 0.153107s [ 吞吐率:6.53req/s ] 内存消耗:4,909.80kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=f2b985698dcd8286a5f83df29de83636
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000477s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000696s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000324s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000269s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000543s ]
  6. SELECT * FROM `set` [ RunTime:0.000238s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000567s ]
  8. SELECT * FROM `article` WHERE `id` = 672871 LIMIT 1 [ RunTime:0.000799s ]
  9. UPDATE `article` SET `lasttime` = 1779806089 WHERE `id` = 672871 [ RunTime:0.006382s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000281s ]
  11. SELECT * FROM `article` WHERE `id` < 672871 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000526s ]
  12. SELECT * FROM `article` WHERE `id` > 672871 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000833s ]
  13. SELECT * FROM `article` WHERE `id` < 672871 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.008896s ]
  14. SELECT * FROM `article` WHERE `id` < 672871 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.009971s ]
  15. SELECT * FROM `article` WHERE `id` < 672871 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.029342s ]
0.157179s