当前位置:首页>python>阿里低调开源了一款Python版的 Arthas工具【PyFlightProfiler - 古法技能篇】

阿里低调开源了一款Python版的 Arthas工具【PyFlightProfiler - 古法技能篇】

  • 2026-04-13 13:55:19
阿里低调开源了一款Python版的 Arthas工具【PyFlightProfiler - 古法技能篇】

先说Arthas:Java程序员的"瑞士军刀"

在Java开发者的工具箱里,Arthas(阿尔萨斯)绝对是一个如雷贯耳的名字。这款由阿里巴巴开源的Java诊断利器,凭借其无侵入、无需重启、实时监控等特性,拯救了无数个被线上Bug折磨的深夜。

Arthas的使用体验极为流畅:你只需要知道目标Java进程的PID,执行 java -jar arthas-boot.jar <pid>,就能进入一个交互式的诊断控制台。在这里,你可以:

  • 用 watch 命令实时观察某个方法的入参、返回值和执行耗时;

  • 用 trace 命令追踪方法内部的调用链路,精确定位每一步的耗时;

  • 用 stack 命令查看某个方法被谁调用,还原完整的调用栈;

  • 用 jad 命令反编译线上的字节码,确认部署的代码是否符合预期;

  • 用 redefine 命令热替换类的实现,在不重启的情况下修复Bug。

Arthas之所以能做到这一切,背后依赖的是JVM提供的两大利器:Java Attach API(用于动态挂载到运行中的JVM进程)和 Java Instrumentation API(用于在运行时对字节码进行增强和替换)。这套机制是JVM规范的一部分,成熟、稳定,且有官方背书。

然而,随着AI时代的到来,Python在生产环境中的比重急剧上升。无论是大模型推理服务、RAG应用,还是各种AI Agent,Python的身影无处不在。但Python开发者在面对线上问题时,往往只能依赖传统的日志打印,或者在本地艰难地复现问题。这种"加日志-重新部署-等待触发-查日志"的循环,不仅效率低下,在生产环境中更是一种奢侈。

就在最近,阿里巴巴低调地开源了一款名为 PyFlightProfiler 的工具。它就像是Python界的Arthas,为线上运行的Python应用程序提供了一种便捷、无侵入的排查手段。

PyFlightProfiler:Python的"飞行记录仪"

PyFlightProfiler 的名字颇有意境——"飞行记录仪"(Flight Profiler),暗示着它的使命:在程序"飞行"的过程中,默默记录下一切关键数据,以便在出现问题时能够还原现场。

PyFlightProfiler is a toolbox that lets you inspect the status of a running Python process. It allows developers to observe method execution, trace call paths, monitor GIL status, and more, without restarting the application.

其核心功能矩阵如下表所示:

命令

功能描述

对应Arthas命令

watch

观察方法的入参、返回值和执行耗时

watch

trace

追踪方法内部的调用链路

trace

stack

打印所有线程的Python调用栈

thread

tt

跨时间段记录方法调用并回放

tt

getglobal

查看模块全局变量和类静态变量

getstatic

vmtool

获取和操作运行中的类实例

vmtool

perf

生成火焰图进行性能热点分析

profiler

console

在目标进程中执行自定义Python脚本

ognl

mem

内存分析,包括内存差异和对象摘要

heapdump

gilstat

监控GIL的获取和释放耗时

(Python特有)

reload

热重载方法实现

redefine

安装方式极为简洁:

pip3 install flight_profiler

挂载到目标进程:

flight_profiler <pid>

使用场景:进程挂载解析

场景描述:

线上服务突然CPU飙升,某个接口响应极慢。你不能重启服务,因为重启会破坏现场,甚至导致服务不可用。你需要立即"潜入"这个进程,一探究竟。

Arthas的做法:

在Java中,Arthas利用了JVM提供的 Attach API。简单来说,JVM在启动时会创建一个特殊的Unix Domain Socket,Arthas通过向这个Socket发送指令,触发JVM加载一个外部的Java Agent(.jar 文件)。这个过程是JVM规范的一部分,安全且有保障。

PyFlightProfiler的原理图解:

Python并没有原生提供这样完善的机制(直到CPython 3.14才引入了 sys.remote_exec,但这是后话)。对于CPython 3.13及以下版本,PyFlightProfiler在Linux环境下采用了一种非常硬核的方式——ptrace 系统调用。

ptrace 是Linux内核提供的一个系统调用,它允许一个进程(Tracer)观察和控制另一个进程(Tracee)的执行,并检查和改变其内存和寄存器。GDB、strace 等经典调试工具都是基于 ptrace 实现的。它是操作系统层面最底层的进程控制机制之一。

让我们深入 csrc/attach/ 目录,看看是如何运作的。

第一步:暂停目标进程

在 ProcessTracer.cpp 中,通过 PTRACE_ATTACH 暂停目标进程:

// ProcessTracer.cppboolProcessTracer::attach(){    // 通过 ptrace 附加到目标进程,目标进程会收到 SIGSTOP 信号并暂停    int result = ptrace(PTRACE_ATTACH, process_id_, NULLNULL);    CHECK_PTRACE_RESULT(result, PTRACE_ATTACH);    int wait_status;    // 等待目标进程真正停下来    if (waitpid(process_id_, &wait_status, WUNTRACED) != process_id_) {        return false;    }    is_attached_ = true;    return true;}

第二步:保存现场,准备注入

在 AttachAgent.cpp 中,保存目标进程的寄存器状态,并计算出 malloc、dlopen、free 等libc函数在目标进程中的地址:

// AttachAgent.cpp (节选)// 保存原始寄存器状态,以便事后恢复process_tracer_.getRegisters(&original_registers);// 计算 malloc/dlopen/free 在目标进程中的地址// 原理:两个进程加载了相同的 libc,函数偏移量相同long current_libc_base = ProcessUtils::getLibcBaseAddress(getpid());long target_libc_base  = ProcessUtils::getLibcBaseAddress(target_process_id_);long target_malloc_addr = target_libc_base + (malloc_addr - current_libc_base);long target_dlopen_addr = target_libc_base + (dlopen_addr - current_libc_base);第三步:注入Shellcode,调用 dlopen这是整个过程最精妙的部分。PyFlightProfiler 将一段汇编代码写入目标进程的内存,这段代码的作用是调用 dlopen 加载 Agent 动态库:// AttachAgent.cpp 中的汇编 Shellcode(节选)void load_shared_library(long malloc_addr, long free_addr,                         long dlopen_addr, long lib_path_len) {    asm(        "and $0xfffffffffffffff0, %%rsp \n"  // 16字节对齐        "callq *%%r8 \n"                     // 调用 malloc,分配内存存放库路径        "int $3 \n"                          // 触发断点,让 Tracer 写入库路径字符串        "pop %%r8 \n"                        // 恢复 dlopen 地址        "mov %%rax, %%rdi \n"               // malloc 返回的内存地址作为 dlopen 的第一个参数        "mov $0x1, %%rsi \n"               // RTLD_LAZY 标志        "callq *%%r8 \n"                     // 调用 dlopen,加载 Agent .so 文件        "int $3 \n"                          // 触发断点,通知 Tracer 加载完成        // ... 调用 free 释放内存 ...        ::: "memory""rax""rcx""rdx""rdi""rsi""r8""r9"    );}

第三步:注入Shellcode,调用 dlopen

这里设计巧妙的地方是 PyFlightProfiler 将一段汇编代码写入目标进程的内存,这段代码的作用是调用 dlopen 加载 Agent 动态库:

// AttachAgent.cpp 中的汇编 Shellcode(节选)void load_shared_library(long malloc_addr, long free_addr,                         long dlopen_addr, long lib_path_len) {    asm(        "and $0xfffffffffffffff0, %%rsp \n"  // 16字节对齐        "callq *%%r8 \n"                     // 调用 malloc,分配内存存放库路径        "int $3 \n"                          // 触发断点,让 Tracer 写入库路径字符串        "pop %%r8 \n"                        // 恢复 dlopen 地址        "mov %%rax, %%rdi \n"               // malloc 返回的内存地址作为 dlopen 的第一个参数        "mov $0x1, %%rsi \n"               // RTLD_LAZY 标志        "callq *%%r8 \n"                     // 调用 dlopen,加载 Agent .so 文件        "int $3 \n"                          // 触发断点,通知 Tracer 加载完成        // ... 调用 free 释放内存 ...        ::: "memory""rax""rcx""rdx""rdi""rsi""r8""r9"    );}

第四步:恢复现场

Agent库被加载后,profiler_attach.cpp 中的 __attribute__((constructor)) 修饰的函数会自动执行,在目标进程中启动一个新的Python线程,运行 profiler_agent.py,建立起与客户端通信的Socket服务器。之后,Tracer 恢复目标进程的寄存器并 PTRACE_DETACH,目标进程恢复正常运行,毫无察觉地被"植入"了一个后台诊断服务。

// profiler_attach.cpp// 这个函数在 .so 被 dlopen 加载时自动执行__attribute__((constructor)) voidprofiler_attach_init() {    // ... 读取参数 ...    profiler_attach(py_code, port, base_addr);}staticintstart_thread() {    // 获取 GIL 锁    PyGILState_STATE old_gil_state = PyGILState_Ensure();    boot->interp = PyThreadState_Get()->interp;    // 启动一个新的 Python 线程来运行 Agent 代码    ident = PyThread_start_new_thread(boot_entry, (void *)boot);    // 释放 GIL 锁    PyGILState_Release(old_gil_state);    return 0;}

对于CPython 3.14+,PyFlightProfiler 则直接使用了官方提供的 sys.remote_exec 接口,这是Python官方在 PEP-768中引入的安全远程代码执行机制,整个过程更加优雅和安全。

使用场景:方法观测——替换字节码

场景描述:

某个推理服务的某个接口P99延迟异常高,你怀疑是某个特定的预处理函数在某些输入下会触发慢路径。你想实时观察这个函数的入参、返回值和执行耗时,但又不能修改代码重新部署。

使用方式:

# 观察 __main__ 模块中 preprocess 函数的入参和返回值watch __main__ preprocess --expr "args, return_obj" -f "cost > 100"# 追踪 model_server 模块 InferenceService 类的 predict 方法内部调用链trace model_server InferenceService predict

原理解析:

在Java中,Arthas通过ASM框架在字节码层面插入探针代码。PyFlightProfiler 同样采用

了字节码替换技术,但它是纯Python实现的,其核心在 flight_profiler/common/bytecode_transformer.py 和 aop_decorator.py 中。

第一步:找到目标函数

aop_decorator.py 通过 importlib.import_module 和 inspect.getmembers 找到目标函数对象:

# aop_decorator.pydef find_module_function(module, method_name):    for name, m in inspect.getmembers(        module, lambda x: inspect.isfunction(x) or inspect.ismethod(x)    ):        if name == method_name:            return m, False    return NoneFalse

第二步:生成Wrapper函数

watch_agent.py 中的 wrapper_generator 生成一个包装函数,它会在目标函数执行前后记录时间、参数和返回值:

# watch_agent.py (节选)def wrapper_generator(watch_setting: WatchSetting):    def watch_func(func):        @functools.wraps(func)        def wrapped(*args, **kwargs):            if watch_setting.enter():                s = time.time()                try:                    return_obj = func(*args, **kwargs)  # 调用原始函数                    e = time.time()                    # 记录并输出观测结果                    watch_setting.dump_result(                        int(s * 1000), target_obj,                        (e - s) * 1000, return_obj, *args, **kwargs                    )                    return return_obj                except Exception as ex:                    # 记录异常信息                    watch_setting.dump_error(...)                    raise ex        return wrapped    return watch_func

第三步:字节码的"偷天换日"

这是整个机制最精妙的地方。PyFlightProfiler 并不是简单地替换函数引用(那样只对新的调用者生效),而是直接替换函数对象的 __code__ 属性。

在Python中,每个函数对象都有一个 __code__ 属性,它是一个 CodeType 对象,包含了函数的字节码指令、常量、变量名等所有编译后的信息。通过替换 __code__,可以在不改变函数引用的情况下,改变函数的行为。

bytecode_transformer.py 中的 _execute_bytecode_transform_intern 函数完成了这个精妙的替换:

# bytecode_transformer.py (核心逻辑简化版)def _execute_bytecode_transform_intern(fn, wrapper_generator, wrapper_arg, ...):    # 1. 生成 Wrapper 函数    wrap_function = wrapper_generator(wrapper_arg)(fn)    wrap_code = wrap_function.__code__    # 2. Wrapper 函数通过闭包(LOAD_DEREF)引用了 watch_setting 和原始函数    #    但我们不能直接用闭包,因为目标函数的自由变量数量是固定的    #    所以要把 LOAD_DEREF 指令替换为 LOAD_CONST 指令    #    将 watch_setting 和原始函数副本作为常量嵌入到新的字节码中    alternate_code = replace_deref_with_const(wrap_code.co_code, ...)    # 3. 创建原始函数的副本,避免无限递归    copy_fn = types.FunctionType(fn.__code__, fn.__globals__, ...)    # 4. 构造新的 CodeType 对象,将 watch_setting 和函数副本追加到常量池    new_codeobj = types.CodeType(        wrap_code.co_argcount, ...,        alternate_code,                        # 替换后的字节码        wrap_code.co_consts + (wrapper_arg, copy_fn),  # 追加常量        ...    )    return new_codeobjdef transform_normal_method_by_aop_wrapper(fn, wrapper_generator, wrapper_arg, ...):    new_codeobj = _execute_bytecode_transform_intern(fn, ...)    # 直接替换函数的 __code__ 属性!    fn.__code__ = new_codeobj

这种方式的妙处在于:由于修改的是函数对象本身的字节码,而不是某个模块中的引用,所以无论这个函数已经被多少个地方导入和缓存,这次修改都会全局生效。这正是它能够实现真正无侵入观测的关键。

使用场景:GIL状态监控

场景描述:

你的多线程Python服务在高并发下性能急剧下降,top 命令显示CPU利用率很低,但线程数量很多。你怀疑是GIL(全局解释器锁)导致的线程争抢,但苦于没有量化数据。

使用方式:

# 监控 GIL 状态,设置警告阈值(单位:毫秒)gilstat --take-cost-warning 10 --hold-cost-warning 50 --stat-interval 5

原理解析:

GIL是CPython的底层C语言机制,纯Python代码无法直接感知它的状态。PyFlightProfiler 借助了 Frida 的底层引擎 frida-gum,在C层面对CPython的内核函数实施了拦截。

在 csrc/py_gil_intercept.cpp 中,它使用 gum_interceptor_attach 拦截了CPython内核中的两个关键函数:take_gil(获取GIL)和 drop_gil(释放GIL):

// py_gil_intercept.cpp (节选)static void python_gil_listener_on_enter(GumInvocationListener *listener,                                          GumInvocationContext *ic) {    PythonGilHookId hook_id = (PythonGilHookId)(gsize)GUM_IC_GET_FUNC_DATA(ic, gpointer);    pthread_t thread_id = pthread_self();    switch (hook_id) {    case PYTHON_GIL_HOOK_TAKE_GIL:        gilStat->on_take_gil_enter(thread_id);  // 记录开始等待 GIL 的时间        break;    case PYTHON_GIL_HOOK_DROP_GIL:        gilStat->on_drop_gil_enter(thread_id);  // 记录开始持有 GIL 的时间        break;    }}// 初始化拦截器gum_interceptor_begin_transaction(interceptor);gum_interceptor_attach(interceptor,    GSIZE_TO_POINTER(take_gil_address),  // take_gil 函数地址    listener,    GSIZE_TO_POINTER(PYTHON_GIL_HOOK_TAKE_GIL));gum_interceptor_attach(interceptor,    GSIZE_TO_POINTER(drop_gil_address),  // drop_gil 函数地址    listener,    GSIZE_TO_POINTER(PYTHON_GIL_HOOK_DROP_GIL));gum_interceptor_end_transaction(interceptor);

通过在 take_gil 的 enter/leave 回调中记录时间差,可以精确计算出每个线程等待GIL的时间(即GIL争抢开销);通过在 drop_gil 的 enter/leave 回调中记录时间差,可以计算出每个线程持有GIL的时间。这些数据对于诊断GIL相关的性能问题极为宝贵。

使用场景:热重载——不停机修复Bug

场景描述:

线上发现了一个逻辑Bug,修复方案已经确定,但重新部署需要走完整的发布流程,至少需要半小时。你能不能先临时修复一下,让服务恢复正常?

使用方式:

# 热重载 model_server 模块 InferenceService 类的 predict 方法reload model_server InferenceService predict

原理解析:

reload_agent.py 中的 ReloadAgent.reload_function 实现了这一功能。其核心思路是:从磁盘上读取最新的源文件,解析出目标函数的源码,重新编译,然后替换运行中函数的 __code__。

# reload_agent.py (核心逻辑简化版)class ReloadAgent:    @staticmethod    def reload_function(module_name, class_name, func_name, verbose):        # 1. 找到目标函数对象        method_target, _, module = find_method_by_mod_cls(            module_name, class_name, func_name        )        # 2. 获取函数所在的源文件路径        method_file_path = inspect.getfile(module)        # 3. 用 AST 解析源文件,精确提取目标函数的源码        class_source, method_source, has_decorators = \            ASTMethodLocator.locate_cls_method_in_file(                method_file_path, func_name, class_name            )        # 4. 将提取的源码包装成类,然后编译执行        wrapped_source = f"class {class_name}:\n{method_source}"        local_ns = {}        exec(compile(wrapped_source, method_file_path, "exec"), {}, local_ns)        new_cls = local_ns[class_name]        new_method = getattr(new_cls, func_name)        # 5. 将新函数的 __code__ 替换到原函数上        method_target.__code__ = new_method.__code__

这个功能的前提是:你已经修改了磁盘上的源文件(但还没有重新部署)。reload 命令会读取最新的文件内容,重新编译,并将新的字节码注入到正在运行的函数中,实现真正的"热修复"。

使用场景:线程栈分析——快速定位阻塞

场景描述:

服务无响应,但进程还在。你怀疑某个线程陷入了死锁或者长时间阻塞。你需要快速查看所有线程当前的调用栈。

使用方式:

# 打印所有线程的 Python 调用栈stack# 打印所有异步协程的调用栈stack async

原理解析:

stack 命令的实现在 server_plugin_stack.py 中,它调用了CPython内置的 _Py_DumpTracebackThreads 函数,将所有线程的调用栈写入一个临时文件,然后读取并格式化输出。

# server_plugin_stack.py (节选)async def do_action(self, param):    # 通过符号解析找到 CPython 内置函数的地址    addr = resolve_symbol_address("_Py_DumpTracebackThreads", os.getpid())    # 调用 C 扩展,将所有线程栈 dump 到临时文件    dump_all_threads_stack(tmp_fd, int(addr))    with open(tmp_file_path, "r"as f:        contents = f.readlines()    # 将线程ID与线程名称关联,增强可读性    await self.out_q.output_msg(        Message(Trueself.add_thread_name(contents))    )

对于异步协程,它则通过访问 asyncio.tasks._all_tasks(Python 3.7-3.11)或 asyncio.tasks._scheduled_tasks(Python 3.12+)这些内部属性,遍历所有运行中的异步任务,并提取其调用栈帧。

结语

下面这张图是 PyFlightProfiler 的整体架构,如果你觉得这个项目对你有所帮助,请访问项目地址( https://github.com/alibaba/PyFlightProfiler)进行深度探索,(别忘了 star 哦: 🤭)。

参考资料:

[1] PyFlightProfiler GitHub Repository: https://github.com/alibaba/PyFlightProfiler

[2] Arthas - Alibaba Java Diagnostic Tool: https://arthas.aliyun.com/

[3] PEP 768 – Safe external debugger interface for CPython: https://peps.python.org/pep-0768/

[4] ptrace(2 ) - Linux manual page: https://man7.org/linux/man-pages/man2/ptrace.2.html

[5] Frida - Dynamic instrumentation toolkit: https://frida.re/

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-15 16:31:05 HTTP/2.0 GET : https://f.mffb.com.cn/a/486106.html
  2. 运行时间 : 0.206695s [ 吞吐率:4.84req/s ] 内存消耗:4,589.72kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=fa90ea7fe91bdbccac675af9dd702af0
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000770s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001174s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000542s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000389s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000859s ]
  6. SELECT * FROM `set` [ RunTime:0.000404s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000929s ]
  8. SELECT * FROM `article` WHERE `id` = 486106 LIMIT 1 [ RunTime:0.003575s ]
  9. UPDATE `article` SET `lasttime` = 1776241865 WHERE `id` = 486106 [ RunTime:0.008527s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000424s ]
  11. SELECT * FROM `article` WHERE `id` < 486106 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000693s ]
  12. SELECT * FROM `article` WHERE `id` > 486106 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.014545s ]
  13. SELECT * FROM `article` WHERE `id` < 486106 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003611s ]
  14. SELECT * FROM `article` WHERE `id` < 486106 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.047127s ]
  15. SELECT * FROM `article` WHERE `id` < 486106 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.012069s ]
0.209351s