#tor #memory #quota #arti #tracking #resistance #reclamation

tor-memquota

用于跟踪和配额工具的内存使用,由Tor软件使用

3个版本 (重大更改)

0.21.0 2024年8月1日
0.20.0 2024年6月27日
0.18.0 2024年4月30日

#114 in 内存管理

Download history 103/week @ 2024-04-26 17/week @ 2024-05-03 87/week @ 2024-06-21 40/week @ 2024-06-28 8/week @ 2024-07-05 62/week @ 2024-07-26 43/week @ 2024-08-02

每月105次下载

MIT/Apache

725KB
11K SLoC

tor-memquota

内存使用配额、跟踪和回收,用于Tor拒绝服务抵抗

许可证:MIT OR Apache-2.0


lib.rs:

预期行为

在正常操作中,我们尝试尽可能少地跟踪状态,成本低廉。我们确实跟踪名义字节的总体内存使用(但略有近似)。

当我们超过配额时,我们采用更昂贵的算法:我们构建一个堆来选择最老的受害者,并使用堆来不断减少内存,直到我们低于一个低水位线(滞后)。

关键概念

  • 追踪器:内存配额系统的实例。每个追踪器都有一个概念,即其参与者可以聚合使用多少内存。跟踪所有账户和参与者的内存使用。不同的追踪器是完全独立的。

  • 账户:同一账户内使用的所有内存都被同等对待,回收也按账户进行。(每个账户与一个追踪器相关联。)

  • 参与者:一个使用内存的数据结构。每个参与者都与一个账户相关联。一个账户有一个或多个参与者。(一个账户可以没有参与者,但不能因此声称内存。)参与者向内存系统提供一个dyn IsParticipant,内存系统反过来向参与者提供一个Participation - 跟踪内存分配/释放的句柄。

  • 子账户/父账户:一个账户可能有一个父账户。当一个追踪器从父账户请求内存回收时,它也会从该父账户的所有子账户请求(但反之则不然)。

  • 数据年龄:每个参与者必须能够说明其存储的最旧数据是什么。回收策略是尝试释放最旧的数据。

  • 内存回收:当追踪器认为内存使用过多时,它将根据数据年龄选择一个受害者账户。然后,它会要求该账户中的每个参与者以及该账户每个子账户中的每个参与者回收内存。参与者将根据回收请求释放至少一些内存,并告诉追踪器它已经完成。

  • 回收策略:为了避免频繁的回收,一旦开始回收,它将一直进行,直到达到一个低水位线,远低于配额。也就是说,系统具有滞后性。

  • 近似(时间和空间):内存配额系统并不完全精确。参与者不需要精确报告其使用情况,但误差应合理小,并且有界。同样,强制执行也不精确:回收可能开始得太早或太晚;但内存使用将被限制在 O(参与者数量)以下,并且在上限为 O(1)(加上来自参与者的误差)。回收不是立即的,并且依赖于任务调度;在内存压力期间,配额可能会超过;在尝试回收时,不会阻止新的分配。

所有权和弧生命周期

  • 某处,某个人必须保留一个 Account 以保持账户开放。也就是说,对应于账户持有人的主要对象应包含一个 Account

  • Arc<MemoryTracker> 包含 Weak<dyn IsParticipant>。如果追踪器发现 IsParticipant 已消失,它假定这意味着参与者正在被销毁,它可以将其声称的所有内存视为已释放。

  • 每个参与者都持有一个 Participation。一个 Participation 可能在底层账户崩溃时失效,这可能以任何方式触发。

  • Participation 不保留其 Account 的生命周期。也就是说,它对账户只有一个弱引用。

  • 参与者 IsParticipant 的实现者可能持有 Participation。如果 impl IsParticipant 也是主要账户持有对象,它必须也持有 Account

  • 子/父账户不表示任何生命周期保持关系。这只是说,向父账户(如果它仍然存在)发出回收请求时,也将向其子账户发出请求。

    accountholder   =======================================>*  Participant
                                                               (impl IsParticipant)
          ||
          ||                                                     ^     ||
          ||                                                     |     ||
          ||                 global                     Weak<dyn>|     ||
          ||                     ||                              |     ||
          \/*                    \/                              |     ||
                                                                 |     ||
        Account  *===========>  MemoryTracker  ------------------'     ||
                                                                       ||
           ^                                                           ||
           |                                                           \/
           |
            `-------------------------------------------------*   Participation



    accountholder which is also directly the Participant ==============\
    (impl IsParticipant)                                              ||
                                          ^                           ||
          ||                              |                           ||
          ||                              |                           ||
          ||                 global       |Weak<dyn>                  ||
          ||                     ||       |                           ||
          \/                     \/       |                           ||
                                                                      ||
        Account  *===========>  MemoryTracker                         ||
                                                                      ||
           ^                                                          ||
           |                                                          \/
           |
            `-------------------------------------------------*   Participation

依赖关系

~12–24MB
~337K SLoC