当前位置:首页>python>Python 并发与 asyncio 6.5 共享数据和锁

Python 并发与 asyncio 6.5 共享数据和锁

  • 2026-01-27 06:49:19
Python 并发与 asyncio 6.5 共享数据和锁

6.5 共享数据和锁

在第 1 章中,我们讨论了在 multiprocessing 中,每个进程都有自己的内存,与其他进程分离。这在我们有共享状态需要跟踪时带来了挑战。那么,如果它们的内存空间各不相同,我们如何在进程之间共享数据?

Multiprocessing 支持一种称为“共享内存对象”的概念。共享内存对象是一块分配的内存,一组独立的进程可以访问。如图 6.2 所示,每个进程都可以根据需要读取和写入该内存空间。

图 6.2 父进程有两个子进程,所有进程共享内存

共享状态很复杂,如果实施不当,会导致难以重现的错误。通常最好避免共享状态。不过,有时确实有必要引入共享状态。一个这样的例子是共享计数器。

为了更深入地了解共享数据,我们将以上面的 MapReduce 例子为基础,保持一个已完成映射操作的计数器。然后,我们定期输出这个数字,以显示用户当前的进度。

6.5.1 共享数据和竞态条件

Multiprocessing 支持两种类型的共享数据:值和数组。一个“值”是一个单一的值,比如一个整数或浮点数。一个“数组”是一个单一值的数组。我们可以在内存中共享的数据类型受到 Python 数组模块中定义的类型的限制,可在 https://docs.python.org/3/library/array.html#module-array(https://docs.python.org/3/library/array.html#module-array) 找到。

要创建一个值或数组,我们首先需要使用数组模块的 typecode,它只是一个字符。让我们创建两个共享的数据项——一个整数值和一个整数数组。然后,我们将创建两个进程来并行增加这两个共享数据项。

列表 6.10 共享的值和数组

from multiprocessing import Process, Value, Arraydef increment_value(shared_int: Value):    shared_int.value = shared_int.value + 1def increment_array(shared_array: Array):    for index, integer in enumerate(shared_array):        shared_array[index] = integer + 1if __name__ == '__main__':    integer = Value('i', 0)    integer_array = Array('i', [0, 0])    procs = [Process(target=increment_value, args=(integer,)),             Process(target=increment_array, args=(integer_array,))]    [p.start() for p in procs]    [p.join() for p in procs]    print(integer.value)    print(integer_array[:])

在上面的代码中,我们创建了两个进程——一个用于增加我们的共享整数值,另一个用于增加我们共享数组中的每个元素。一旦两个子进程完成,我们就打印出数据。

由于我们的两块数据从未被不同进程触碰,这段代码运行得很好。如果多个进程修改同一个共享数据,这段代码还能继续工作吗?让我们通过创建两个进程来并行增加一个共享整数值来测试一下。我们将在这段代码上反复运行一个循环,以查看结果是否一致。由于我们有两个进程,每个都把共享计数器加一,一旦进程完成,我们期望共享值始终为二。

列表 6.11 并行增加共享计数器

from multiprocessing import Process, Valuedef increment_value(shared_int: Value):    shared_int.value = shared_int.value + 1if __name__ == '__main__':    for _ in range(100):        integer = Value('i', 0)        procs = [Process(target=increment_value, args=(integer,)),                 Process(target=increment_value, args=(integer,))]        [p.start() for p in procs]        [p.join() for p in procs]        print(integer.value)        assert(integer.value == 2)

虽然你会看到不同的输出,因为这个问题是非确定性的,但在某个时候,你应该会看到结果并不总是 2。

222断言错误 (AssertionError)1

有时候我们的结果是 1!为什么会这样?我们遇到的问题叫做“竞态条件”。竞态条件发生在一组操作的结果依赖于哪个操作先完成时。你可以想象这些操作在彼此竞争;如果操作以正确的顺序赢得比赛,一切都会正常。如果它们以错误的顺序赢得比赛,就会出现奇怪的行为。

那么,我们的例子中竞态在哪里发生?问题在于增加一个值涉及读取和写入操作。要增加一个值,我们首先需要读取该值,加一,然后将结果写回内存。每个进程在共享数据中看到的值完全取决于它读取共享值的时间。

如果进程以以下顺序运行,一切都会正常,如图 6.3 所示。

在这种情况下,进程 1 在进程 2 读取之前增加了值,并赢得了比赛。由于进程 2 是第二个完成的,这意味着它会看到正确的值 1,并加上去,从而产生正确的最终值。

图 6.3 成功避免竞态条件

如果我们的虚拟比赛中出现平局怎么办?请看图 6.4。

图 6.4 竞态条件

在这种情况下,进程 1 和进程 2 都读取了初始值 0。然后它们都将该值增加到 1,并同时写回,产生了错误的值。

你可能会问:“但我们的代码只有一行。为什么会有两个操作!?” 在底层,增加是作为两个操作编写的,这导致了这个问题。这使得它“非原子”或“非线程安全”。这不容易弄清楚。有关哪些操作是原子的,哪些是非原子的解释,可在 http://mng.bz/5Kj4(http://mng.bz/5Kj4) 找到。

这类错误很难,因为它们往往难以重现。它们不像普通错误,因为它们依赖于操作系统运行事物的顺序,而这在使用 multiprocessing 时是不受我们控制的。那么,我们该如何修复这个烦人的错误呢?

6.5.2 使用锁进行同步

我们可以避免竞态条件,通过“同步”对任何我们想要修改的共享数据的访问。所谓同步访问是什么意思?重新审视我们的竞态例子,这意味着我们控制对任何共享数据的访问,使得任何操作都能以一种合理的方式完成比赛。如果一个情况可能发生两个操作之间的平局,我们明确阻止第二个操作运行,直到第一个完成,确保操作以一致的方式完成比赛。你可以想象这就像终点线上的裁判,看到平局即将发生,告诉跑者:“稍等一下。一次一个!” 并挑选一个跑者等待,让另一个跑者冲过终点线。

一种同步访问共享数据的机制是“锁”,也称为“互斥锁”(mutex)(意为“互斥”)。这些结构允许一个进程“锁定”一段代码,防止其他进程运行该代码。被锁定的代码段通常被称为“临界区”。这意味着如果一个进程正在执行被锁定的代码段,而另一个进程试图访问该代码,第二个进程将需要等待(被裁判阻止),直到第一个进程完成对该锁定段的执行。

锁支持两个主要操作:获取释放。当一个进程获取锁时,它保证自己是唯一运行该代码段的进程。一旦需要同步访问的代码段完成,我们就释放锁。这允许其他进程获取锁并运行临界区中的任何代码。如果一个进程尝试运行被另一个进程锁定的代码,获取锁将阻塞,直到另一个进程释放该锁。

重新审视我们的计数器竞态条件示例,并参考图 6.5,让我们可视化当两个进程几乎同时尝试获取锁时会发生什么。然后,让我们看看它如何防止计数器获得错误的值。

图 6.5 进程 2 被阻塞,直到进程 1 释放锁才能读取共享数据。

在该图中,进程 1 首先成功获取锁,读取并增加共享数据。第二个进程尝试获取锁,但被阻止,无法进一步推进,直到第一个进程释放锁。一旦第一个进程释放锁,第二个进程就可以成功获取锁并增加共享数据。这防止了竞态条件,因为锁防止了多个进程同时读取和写入共享数据。

那么,我们如何用我们的共享数据实现这种同步?multiprocessing API 的开发者想到了这一点,并很好地包含了获取值和数组锁的方法。要获取锁,我们调用 get_lock().acquire(),要释放锁,我们调用 get_lock().release()。使用列表 6.12,让我们将这应用于我们之前的例子以修复我们的错误。

列表 6.12 获取和释放锁

from multiprocessing import Process, Valuedef increment_value(shared_int: Value):    shared_int.get_lock().acquire()    shared_int.value = shared_int.value + 1    shared_int.get_lock().release()if __name__ == '__main__':    for _ in range(100):        integer = Value('i', 0)        procs = [Process(target=increment_value, args=(integer,)),                 Process(target=increment_value, args=(integer,))]        [p.start() for p in procs]        [p.join() for p in procs]        print(integer.value)        assert (integer.value == 2)

当我们运行这段代码时,我们得到的每个值都应该是 2。我们已经修复了竞态条件!请注意,锁也是上下文管理器,为了清理代码,我们可以使用 with 块来编写 increment_value 函数。这将为我们自动获取和释放锁:

def increment_value(shared_int: Value):    with shared_int.get_lock():        shared_int.value = shared_int.value + 1

请注意,我们已经将并发代码强制变为顺序执行,这抵消了并行运行的价值。这是一个重要的观察,也是并发中同步和共享数据的一个警告。为了避免竞态条件,我们必须使我们的并行代码在关键部分顺序执行。这可能会损害我们的 multiprocessing 代码的性能。必须仔细权衡,只锁定绝对必要的部分,以便应用程序的其他部分可以并发执行。面对竞态条件错误时,很容易用锁保护所有代码。这将“修复”问题,但很可能降低应用程序的性能。

6.5.3 使用进程池共享数据

我们刚刚看到了如何在几个进程中共享数据,那么如何将这些知识应用到进程池中呢?进程池的操作方式与手动创建进程略有不同,这给共享数据带来了挑战。为什么是这样?

当我们向进程池提交一个任务时,它可能不会立即运行,因为池中的进程可能正忙于其他任务。进程池是如何处理这个问题的?在后台,进程池执行器会维护一个任务队列来管理这一点。当我们向进程池提交一个任务时,它的参数会被序列化(腌制)并放入任务队列。然后,每个工作进程在准备好工作时,会从队列中请求一个任务。当一个工作进程从队列中取出一个任务时,它会反序列化(解腌制)参数并开始执行任务。

共享数据从定义上讲是在工作进程之间共享的。因此,来回发送它进行腌制和解腌制毫无意义。事实上,ValueArray 对象都无法被腌制,所以如果我们像以前一样将共享数据作为参数传递给函数,我们会收到类似 can't pickle Value objects 的错误。

为了解决这个问题,我们需要将我们的共享计数器放在一个全局变量中,并以某种方式让我们的工作进程知道它。我们可以使用“进程池初始化器”来做到这一点。这些是特殊函数,当池中的每个进程启动时都会被调用。通过这种方式,我们可以创建一个引用,指向父进程创建的共享内存。我们可以在创建进程池时传入这个函数。为了看看它是如何工作的,让我们创建一个简单的例子来增加一个计数器。

列表 6.13 初始化进程池

from concurrent.futures import ProcessPoolExecutorimport asynciofrom multiprocessing import Valueshared_counter: Valuedef init(counter: Value):    global shared_counter    shared_counter = counterdef increment():    with shared_counter.get_lock():        shared_counter.value += 1async def main():    counter = Value('d', 0)    with ProcessPoolExecutor(initializer=init,                             initargs=(counter,)) as pool:                # ❶        await asyncio.get_running_loop().run_in_executor(pool, increment)        print(counter.value)if __name__ == "__main__":    asyncio.run(main())
  • 这告诉池为每个进程执行函数 init,并传入参数 counter

我们首先定义一个全局变量 shared_counter,它将包含对创建的共享 Value 对象的引用。在我们的 init 函数中,我们接收一个 Value 并将 shared_counter 初始化为该值。然后,在主协程中,我们创建计数器并将其初始化为 0,然后将我们的 init 函数和计数器传入 initializerinitargs 参数,以创建进程池。init 函数将为进程池创建的每个进程调用一次,正确地将我们的 shared_counter 初始化为我们在主协程中创建的那个。

你可能会问:“为什么我们要费这么多事?难道我们不能直接将全局变量初始化为 shared_counter: Value = Value('d', 0) 而不是让它为空吗?” 我们不能这样做的原因是,当每个进程被创建时,我们创建它的脚本会被再次运行,每个进程都如此。这意味着每个启动的进程都会执行 shared_counter: Value = Value('d', 0),这意味着如果有 100 个进程,我们会得到 100 个 shared_counter 值,每个都设置为 0,导致一些奇怪的行为。

现在我们知道如何使用进程池正确初始化共享数据,让我们看看如何将其应用到我们的 MapReduce 应用程序中。我们将创建一个共享计数器,每次映射操作完成时就增加一次。我们还将创建一个 progress_reporter 任务,它将在后台运行,每秒向控制台输出一次进度。为了这个例子,我们将导入一些围绕分区和减少的代码,以避免重复。

列表 6.14 跟踪映射操作进度

from concurrent.futures import ProcessPoolExecutorimport functoolsimport asynciofrom multiprocessing import Valuefrom typing import List, Dictfrom chapter_06.listing_6_8 import partition, merge_dictionariesmap_progress: Valuedef init(progress: Value):    global map_progress    map_progress = progressdef map_frequencies(chunk: List[str]) -> Dict[str, int]:    counter = {}    for line in chunk:        word, _, count, _ = line.split('\t')        if counter.get(word):            counter[word] = counter[word] + int(count)        else:            counter[word] = int(count)    with map_progress.get_lock():        map_progress.value += 1    return counterasync def progress_reporter(total_partitions: int):    while map_progress.value < total_partitions:        print(f'已完成 {map_progress.value}/{total_partitions} 个映射操作')        await asyncio.sleep(1)async def main(partiton_size: int):    global map_progress    with open('googlebooks-eng-all-1gram-20120701-a', encoding='utf-8') as f:        contents = f.readlines()        loop = asyncio.get_running_loop()        tasks = []        map_progress = Value('i', 0)        with ProcessPoolExecutor(initializer=init,                                 initargs=(map_progress,)) as pool:            total_partitions = len(contents) // partiton_size            reporter = asyncio.create_task(progress_reporter(total_partitions))            for chunk in partition(contents, partiton_size):                tasks.append(loop.run_in_executor(pool, functools.partial(map_frequencies, chunk)))            counters = await asyncio.gather(*tasks)            await reporter            final_result = functools.reduce(merge_dictionaries, counters)            print(f'Aardvark 出现了 {final_result["Aardvark"]} 次。')if __name__ == "__main__":    asyncio.run(main(partiton_size=60000))

除了初始化共享计数器之外,与我们原始的 MapReduce 实现相比,主要的变化在于我们的 map_frequencies 函数内部。在完成该块中所有单词的计数后,我们获取共享计数器的锁并增加它。我们还添加了一个 progress_reporter 协程,它将在后台运行,并每秒报告一次我们完成了多少个任务。运行此代码时,你应该会看到类似以下的输出:

已完成 17/1443 个映射操作已完成 144/1443 个映射操作已完成 281/1443 个映射操作已完成 419/1443 个映射操作已完成 560/1443 个映射操作已完成 701/1443 个映射操作已完成 839/1443 个映射操作已完成 976/1443 个映射操作已完成 1099/1443 个映射操作已完成 1230/1443 个映射操作已完成 1353/1443 个映射操作Aardvark 出现了 15209 次。

现在我们知道如何使用 multiprocessing 与 asyncio 来提升计算密集型工作的性能。如果我们的工作负载既有大量的计算密集型操作,又有 I/O 密集型操作,该怎么办?我们可以使用 multiprocessing,但有没有办法结合 multiprocessing 和单线程并发模型来进一步提升性能?

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-08 04:10:59 HTTP/2.0 GET : https://f.mffb.com.cn/a/467352.html
  2. 运行时间 : 0.108537s [ 吞吐率:9.21req/s ] 内存消耗:4,664.34kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=5d1008ffa88e6018efc95e4f282032d8
  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.000675s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000815s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000463s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000281s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000468s ]
  6. SELECT * FROM `set` [ RunTime:0.000219s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000516s ]
  8. SELECT * FROM `article` WHERE `id` = 467352 LIMIT 1 [ RunTime:0.004449s ]
  9. UPDATE `article` SET `lasttime` = 1770495059 WHERE `id` = 467352 [ RunTime:0.004648s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.002660s ]
  11. SELECT * FROM `article` WHERE `id` < 467352 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000508s ]
  12. SELECT * FROM `article` WHERE `id` > 467352 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000546s ]
  13. SELECT * FROM `article` WHERE `id` < 467352 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.007219s ]
  14. SELECT * FROM `article` WHERE `id` < 467352 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.007163s ]
  15. SELECT * FROM `article` WHERE `id` < 467352 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.007998s ]
0.110330s