【论文阅读】内存数据库并发控制算法的实验研究

内存数据库并发控制算法的实验研究

原文链接jos.org.cn/jos/article/pdf/6454

摘要

并发控制算法的基本思想归纳为"先定序后检验”,基于该思想对现有各类并发控制算法进行 了重新描述和分类总结,于在开源内存型分布式事务测试床 3TS 上的实际对比实验。

  • 3TS:

    3TS: Tencent Transaction Processing Testbed System(简称3TS),是腾讯公司CynosDB(TDSQL)团队与中国人民大学数据工程与知识工程教育部重点实验室,联合研制的面向数据库事务处理的验证系统 (gitee.com) 目前,验证系统已集成13种主流的并发控制算法,提供了TPC-C、PPS、YCSB等常见基准测试。3TS还进一步提供了一致性级别的测试基准,针对现阶段分布式数据库系统的井喷式发展而造成的系统选择难问题,提供一致性级别判别与性能测试比较。


数据库中的事务需要具备 4 大特性: 原子性(A)、一致性©、隔离性(I)和持 久性(D). 原子性要求事务的操作要么全做, 要么全不做; 一致性要求事务的执行必须使数据库从一个一致性 状态变迁到另一个一致性状态, 不允许未成功提交事务的临时数据被访问; 隔离性要求事务的执行不能影响 其他事务也不能被其他事务影响; 持久性要求数据库持久化存储已提交事务写入的数据. 数据库系统为了保 证 ACID 特性, 引入故障恢复子系统来保证原子性和持久性, 并引入并发控制子系统来保证一致性和隔离性.

设计并发控制算法做到正确且高效仍面临以下两大挑战:

  • 在保证可串行化隔离级别的前提下, 保证事务处理的高效性是一个挑战;
  • 并发控制算法的处理逻辑需要针对基于内存的数据库架构进行调整。
    • 内存数据库相比磁盘数据库,降低了回滚率和磁盘I/O对算法整体性能的影响程度,CPU 的计算处理性能反而成为内存数据 库的主要瓶颈⇒ 主要取决于CPU的性能。以锁机制为 例, 磁盘数据库系统往往会使用细粒度的锁来减少锁争用, 而在内存数据库中就可以使用粗粒度的锁来减少维护锁的计算开销。
    • 磁盘数据库需要单独设计存储结构来在内存中维护元数据,然而内存数据库元数据直接放在数据项的头部。

采用内存数据库可以更直接地评估并发控制算法的效率,因为不需要考虑内外存 I/O 的影响。如何利用内存数据库具备的高速数据读取的优点, 设计并优化并发控制算法, 是当前的另一大挑战。

先定序后检验:即并发控制算法可以统一理解为先对事务进行定序——规定算法要求的事务执行顺序; 之后检测事务实际的执行是否满足这个定序要求, 如不符合, 则事务需要回滚。

在开源的内存型分布式事务测试床 3TS 上,在相同的分布式场景下进行了并发控制算法的实验测试:两阶段封锁、乐观并发控制、时间戳排序(timestamp ordering,T/O)、快照隔离(snapshot isolation, SI) 等比较传统的算法以及 MaaT、Calvin 等近年来提出的部分算法进行总结分析

并发控制算法优缺点
2PC、T/O、MVTO、MV2PC、Silo适合低冲突率下的应用场景
Calvin确定性算法受冲突率以及写事务比例影响小,适合于高冲突和分布式事务
写快照隔离write snapshot isolation WSI低中高冲突率场景下都有不错的表现
Sundial回滚率低 适合中高冲突场景

Untitled

1 数据库并发控制算法的基本思想

评估一种算法是否可以避免所有数据异常的黄金法则是可串行化, 即判断并发事务的执行结果是否与某 一串行执行这些事务的结果等价: 若等价, 则认为该算法调度后的并发事务序列是可以避免所有数据异常的。本文创新性地将并发控制算法的核心思想归纳为"先定序后检验"。

1.1 定序

定序是指为并发事务确定一个等价可串行化调度中事务的先后顺序.

  • 静态定序:即按照事务进入某个处理阶段的先后顺序来确定顺序. 使用该方法的典型算法有T/O、OCC等算法. 太过于严格,可能执行的时候的事务顺序是另外一种串行序列,导致不必要的rollback。
  • 动态定序是指: 根据执行过程中的操作结果, 动态地调整事务在最终串行执行序列中的先后关系. 动态调整顺序的依据 就是数据库中的 3 种依赖: 读写依赖、写读依赖和写写依赖。如 MaaT、Sundial 等算法, 均采用了动态定序的方式

动态定序的方式必然需要增加监控事务之间依赖的开销, 但是更灵活的事务顺序会带来较低的回滚率. 静态定序的方式虽然无须增加监控事务依赖的开销, 但是会引入不必要的回滚.

Untitled

1.2 检验

检验指检查事务的实际操作是否满足定序步骤中规定的事务先后顺序. 核心问题包括: (1) 如何检验; (2) 何时检验.

  • 如何检验

    Untitled

    • 检验冲突:只关注事务执行过程中是否存在并发事务的冲突操作与自己访问了相同的数据项(是否有数据冲突)。如果有,则等待或者回滚。主流的 2PL 以及OCC 等算法均采用了检验冲突的方式. 2PL 算法在读写操作时, 通过加锁来检验是否存在读写、写写冲突. OCC 算法则是在事务提交之前检验是否存在读写冲突, 即检查全局是否有其他事务修改了自己的读集 Rset.

    • 检验依赖:通过检验事务执行操作产生的数据依赖关系和事先规定的顺序是否相同, 来判断是否需要回滚。

      • T1先开始,然后T2开始,但是在T1 WRITE(X) 发现X被T2修改过,所以T1依赖T2,写作T2→T1(ww),与事务开始的顺序相反所以依赖问题,回滚T1.

      Untitled

      • 冲突只关注并发事务是否存在对相同数据项的冲突操作, 依赖则关注两个事务之间的先后顺序; 其检验思路不同, 检验冲突是通过规避和解决并发事务的冲突操作来做到可串行化,检查依赖则是根据 3 种依赖体现的事务先后关系来整理出一个可串行化序列, 若两个事务之间存在完全相反的依赖顺序,则两者之中必须回滚一个来达到可串行化.
    • 检验冲突和检验依赖相结合:

      • 对于写写冲突, 利用加锁来解决.
      • 对于写读依赖, 利用预写操作来解决. 预写使得事务只有提交时才会更新数据项, 因此写读依赖仅仅会发生在当前事务与已提交的写事务之间, 因此无须处理
      • 对于读写依赖, 利用数据项上维护的时间戳信息来检查读写依赖是否存在.
  • 何时检验?除了calvin之外可以将事务拆分成三个执行阶段

    • 读写操作阶段read-write phase:执行读写操作
    • 验证阶段validation phase:检验事务是否可以提交,一般针对OCC和SI
    • 结束阶段finish phase:执行事务的提交或者rollback
  • T/O 算法在读写操作阶段进行检验, 可以尽早检验出不可串行化的事务并将其回滚. OCC 算法则在验证阶段单独对冲突或者依赖进行检验, 提高了事务在读写时的并发度。Sundial 选择了在写操作时检验写写冲突, 在验证阶段 检验读写依赖。

1.3 定序方式与检验方式可能的组合

Untitled

  • 第一象限是静态定序与检验依赖的组合:预先设定一个静态的顺序, 然 后检验实际出现的事务依赖关系是否满足该顺序
  • 第二象限是静态定序与检验冲突的组合:这种组合只需要维护较少的数据结构, 但是会造成最多的假冲突,OCC Calvin。
  • 第三象限中, 动态定序与检验冲突的组合是不可能的, 因为动态定序的基础是事务之间的事务依赖,而检验冲突无法为动态定序提供顺序上的帮助.
  • 第四象限中动态定序方式与检验依赖方式:最直接的一种算法就是根据事务之间的依赖构建出事务依赖图, 并在其中检查是否存在环路。MaaT 通过计算时间戳的方式, 一定程度上减少了构建事务依赖的 开销.

2 两阶段封锁算法(2PL)

思路:根据冲突加锁的先后排定事务顺序, 通过加锁操作检查事务之间的冲突. 事务在读操作时添加读锁(RL)、写操作 时添加写锁(WL), 在提交或者回滚时释放所有锁.

为了预防或解除死锁, 2PL 提供了多种方式: (1) NO-WAIT; (2) WAIT-DIE ; (3) WOUND-WAIT; (4) 死锁检验

  • NO-WAIT 机制是指当加锁发生冲突时, 立刻回滚当前事务。优点:实现简单。缺点:是长事务和其他事务产生冲突的可能性较大, 有可能被饿死。
  • WAIT-DIE 机制是指在检测到冲突时, 根据事务之间的优先级选择处理方式, 即等待(WAIT)或回滚(DIE).可以使用开始时间戳T.start_ts来确定事务的优先级。优点:增加比较优先级的方式避免了事务饿死的情况。缺点:锁算法下的冲突率依然较高。
  • WOUND-WAIT:根据事务优先级来待(WAIT)或抢占锁(WOUND). 若当前事务的优先级较高, 则当前事务抢占锁并回滚之前的锁拥有者; 否 则, 当前事务需要等待.

整体上,2PL方法简单、节省内存、辕信息维护开销少,但是静态定序+检验冲突导致高回滚,不适用于冲突率较高的场景。

3. 乐观并发控制算法OCC

OCC思想:仅在提交之前进行验证, 检查当前事务是否与并发事务存在读写/写写冲突。

3.1 传统OCC

以事务进入验证阶段的时间排序, 并在验证阶段检测并发事务之间是否存在冲突. 为了检测并发事务之间的冲突, 在 OCC 中, 所有事务都需要维护 start_ts (事务的开始时间戳)和 end_ts (事务进入验证时的时间戳), 用于判断当前事务和另一个事务是否并发.还需要对每个事务单独维护一个 Rset(读集)和 Wset (写集): Rset 代表当前事务读取过的数据项 X 的集合, 其中每个元素 Rset[X]包含读到的数据 data; Wset 代表当前事务准备修改的数据项 X, 其中每个元素 Wset[X]包含准备写入的新数据 data.

缺点:1. 只读事务也需要进行验证。2. 额外维护大量写集进行检查,内存开销和验证开销大。

BOCC(back) FOCC(Forward):验证阶段只检查当前事务的写集是否与活跃事务(正在读写阶段的事务)的读集 ActiveRset 存在交集. 相较于 BOCC, FOCC的只读事务无须验证, 整体上减少了验证的开销.

Untitled

难以应用到分布式系统,于是提出并发验证的OCC算法:把所有事务的写集分成History(已经提交事务的写集)和Active(验证阶段的事务的写集),拆分验证阶段变成几个临界区段来增加并发度,事务 T 验证前先在第 1 个临界区内将自己的写集存入 Active, 保证可以被后进入验 证的事务发现, 并拷贝一份现有 History 和 Active. 之后, 事务 T 通过与读集的对比, 验证两个结构内的写集.验证通过后, 进入第 2 个临界区, 将自己从 Active 中清除并写入 History.(好复杂)

3.2 Silo

OCC 的优化算法 Silo:事务根据进入验证阶段的时间确定顺序, 在验证阶段通过检测自己的读集是否被其他事务修改进行检验. Silo 需要在数据项上维护数据项修改时间戳 wts 用于判断读写冲突, 并额外维护 txn_id 写锁用 于避免写写冲突. 在事务中则需要维护读集 Rset 和写集 Wset, 记录读写过的数据项.还需要额外记录读取时数据项的元信息。

验证阶段:第 1 步需要对写集中的数据加锁. 为了防止加锁过程中发生死锁, 加锁前需要对写集的数据进行排序。第 2步, 检查读集中数据是否被其他事务加锁或 wts 信息是否改变, 以此来判断是否存在读写冲突.在验证通过 后, 解锁并写入新数据. txn_id表示拥有写锁的事务id?

事务 T2 在提交时修改数据项的 wts, T1 验证时发现数据项 X 的 wts 与读操 作时不同, 从而回滚.Silo 通过数据项来检验冲突, 大大减少了验证阶段所需的操作; 其次, Silo 算法下多个事务并发验证, 提 高了事务执行的并发度。仍需维护 读写集

Untitled

3.3 Maat

动态时间戳,动态定序+检验依赖关系;依据事务之间的依赖来确定事务的可串行化调度的先手顺序,在验证阶段调整事务的时间戳范围来体现?先后关系。

每个数据项X需维护:1. readers:读取该数据项X但是没提交的事务id;2. Writers:表准备写该数据项但未提交的事务;3. wts:最后一次写当前数据项X并且已提交的事务的时间戳。4. rts:表最后一次读取当前数据项的已提交事务时间戳

每个事务T需要维护:1. Rset 读集 2.Wset:写集 3.时间戳范围[lower,upper) 类似于生命周期?体现事务的先后顺序。4. before:表应在当前事务之前提交的未提交事务队列 5.after:应在当前事务之后提交的未提交事务队列 6.other_writes:代表和当前事务修改相同数据项的未提交事务队列 7.max_rts:访问过的数据项X中最大的 rts 8.max_wts:代表访问过的数据项中最大的 wts.

  1. T1读X 更新readers
  2. T2 WX,更新writers,根据readers发现T1→T2依赖关系
  3. T2验证阶段,调整事务信息,更新T1的upper 为1,也就是T1该在1的时候就commit才行?T2为[1,inf)表示T2 1之后开始?主要是在验证阶段通过更新事务的信息来定序。
  4. T1进入验证阶段,因为要让lower 大于数据项 X 的 wts,所以lower =2 > 1 = upper不对?T1 rollback。

Untitled

3.4 Sundial

动态定序+混合检验,动态计算提交的时间戳来动态的确定顺序,结合OCC+2PL来检验十五是否满足先后顺序,在数据项上维护租约(数据项可以被访问的事务的时间戳范围 )来判断事务的先后顺序。

用OCC验证读写和写读依赖,用加锁解决写写冲突。Sundial中每个数据项需要维护元信息:1. txn_id,锁?2. 租约logic-lease→ wts+rts,如果满足wts≤T.commit_ts≤rts 事务可以读取该数据,commit_ts是事务维护的动态计算的提交时间戳,以及Rset、Wset。

Untitled

过于简短没看懂,原文链接:people.csail.mit.edu/devadas/pubs/sundial.pdf

**总结:**Silo 算法的优点在 于检验和维护数据项元信息开销较小, 但也因此产生了回滚率较高的缺陷,适用于冲突率较低的场景Sundial 算法则兼顾了动态定序的低回滚和混合检验的高效 率, 在中高冲突率下性能依然较好.此低冲突率场景下性能依然比 Silo 算法差,推荐在低冲突率下使用 Silo 算法, 在中高冲突率下选择 Sundial 算法.

4 时间戳排序算法

静态定序+检验依赖。在事务开始时, 为其分配开始时间戳, 并按照开始时间戳对事务进行排序. 在执行读写操作时, 检测当前事务的实际执行顺序是否违背预先规定的顺序: 如果与预定顺序不符, 当前事务需要回滚或者陷入等待.

在事务数据结构中维护:start_ts 开始时间戳,data数据项的值,wts 代表写入当前数据项的事务时间戳;rts代表最后一次读取当前数据项的事务时间戳. 维护wts rts来记录对数据项的更改,进而检查依赖。基础时间戳排序算法的问题:若事务 T1 修改了数据项 X, 之后, T2 在 T1 的基础上再次修改 X, 此时若 T2 提交而 T1 回滚, 将无法确定 X 应当回滚到的版本。

引入两阶段提交,增加预写操作。事务写操作时不将新数据写入数据库, 而是将新数据暂存, 待事务提交时再将新数据写 入. 预写操作解决了无法处理回滚的问题, 但会影响读取操作的正常执行: 假如一个时间戳更大的读事务在 读取数据时发现一个时间戳更小的写事务尚未提交, 为了满足时间戳顺序, 读事务必须等待.

额外维护min_pts 表示数据项上所有与写操作的最小时间戳;read_reqs 代表当前数据项上等待的读操作;pre_reqs 代表当前数据项上的预写操作;write_reqs表示数据项上等待的提交操作。

Untitled

5 多版本并发控制

MVCC 可以将事务对数据 项的操作转化为对数据项版本的操作, 从而提高并发度, 提供读写互不阻塞的能力. 但是 MVCC 本身没有处 理事务冲突的机制, 所以一般需要结合 T/O、2PL、OCC 来做到可串行化.

5.1 MVTO 时间戳排序机制+多版本并发控制

将时间戳作为读取数据项某个版本的依据.通过事务的开始时间戳确定事务顺序, 在读写操作时, 检测实际执行产生的 3 种依赖是否违背时间戳规定的顺序.

start_ts 事务的开始时间戳。数据项版本要维护:data、wts:写入当前版本的事务时间戳(版本的提交时间戳);当事务的 start_ts 大于 wts 时, 该版本对事务可见; rts:成功读过该版本的所有事务 的时间戳的最大值,事务的 start_ts 大于所有版本的 rts 时, 该事务可对当前数据项进行修改。txn_id, 代表当 前正在写入该版本的事务号, 可以理解为写锁, 用于避免写写冲突。

Untitled

5.2 MV2PL 两阶段封锁+多版本并发控制

通过加锁的先后顺序为事务定序, 在读写操作阶段,借助锁机制处理事务之间的冲突. 和2PL相比MV2PL下的读写锁等信息被维护在数据项的每一 个版本上, 包括 txn_id(写锁), read_cnt(读锁数量)以及 wts(当前版本写入时间戳).

Untitled

5.3 乐观并发控制+多版本并发控制

Cicada是OCC(Silo) + MVCC,cicada要维护1. status 当前版本的状态(PENDING 代表当前版本尚未提交, COMMITTED 代表当前版本已经提交, ABORTED 代表当前版本 已被回滚); 2. wts代表当前版本的提交时间戳; 3. rts, 代表读取过当前版本的已提交事务的最大时间戳.

5.4 快照隔离Snapshot Isolation算法

静态定序 + 检验依赖,读写混合事务根据提交时间戳,只读事务通过开始时间戳确定顺序。检验写写冲突和写读依赖来并发控制。对写写冲突:SI 规定: 数据项不能被两个事务同时修改, 并遵循"先提交者获胜策略”.先提交的事务成功, 后提交的事务回滚. . SI 在 MVCC 方法的基础上, 利用快照读(读取事务开始时符合一致性状态的数据)事务的弱隔离级别之快照隔离 - 知乎 (zhihu.com)处理写读依赖.没有对读写依赖进行限定, SI 算法并不能达到可 串行化.

  • SSI
    • 在 SI 的基础上检测连续的读写依赖(只要在 SI 基础上避免出现 T i 读写依赖于 T j、T j 读写依赖于 T k 的情况, 就能达到可串行化)。
    • (1) txn_id, 用于基础 SI 算法处理写写冲突(2) SIRead-Lock, 记录 读取过该数据项的所有事务, 用于协助事务判断是否存在读写依赖.每个版本需要记录提交时间戳 wts 和写 入该版本的事务号 creator.每个事务 T 上需要维护开始时间戳 start_ts 和提交时间戳 commit_ts为了检 测读写依赖, 还需要额外维护 inConflict 和 outConflict, 分别代表读写依赖于 T 的事务和被 T 读写依赖的事务.

Untitled

  • WSI
    • WSI 将对写写冲突的检测转化为对读写依赖的检测, 并通过处理读写依赖来达到可串行化.

6 确定性并发控制算法——Calvin

应用在预先知道事务的全部 SQL 语句的场景中。主要思想:预先为事务确定顺序, 之后强制按照确定的顺序执行事务, 以避免分布式协调的开销.额外两个模块:定序器(sequencer)和调度器(scheduler)定序器用于拦截事务并且为这些事务确定顺序,即事务进入定序器的顺序; 调度器负责按照事务顺序为事务加锁, 保证事务的执行严格按照确定顺序。

一个事务T的执行流程:事务 T 被定序器截获并放入一个 batch 中, 根据事务的截获顺 序排序. 在经过一个固定周期后, 定序器将事务 T 所在的 batch 发送给对应的参与者节点. 参与者节点的调度 器接收 batch, 根据 batch 中事务的顺序加锁.

Untitled

7. 并发控制算法实验评价

评估并发控制算法的标准:吞吐量和回滚率

负载:YCSB + TPCC,其中YCSB事务访问服从Zipf分布,即长尾分布(少量数据获得大量访问)

  • 长尾分布

    长尾分布数据是一种偏态分布,是指几个类别(亦叫头类)包含大量的样本,而大多数类别(亦叫尾类)只有非常少量的样本。

    Untitled

    7.2 冲突率

Untitled

  • 低冲突率下性能:WSI > MVTO > Wait die
  • 中冲突率下性能:MVTO > WSI > Sundial
  • 高冲突率下性能:Calvin

7.3 写操作比例

除 Calvin 和 Sundial 以外的算法, 吞吐量都随着写事务比例的升高而下降.

Untitled

7.4 事务涉及节点数

Calvin 各个节点上子事务可以并发执行, 而且子 事务之间的网络开销和调度开销仅有 1 次, 因此在跨节点数较多的情况下, Calvin 效果较好.

Untitled

7.5 可扩展性

固定事务的最大涉及节点数, 调整分布环境中的总节点数 从 2 到 16 来分析不同算法的性能表现,4 种场景, 分别是 YCSB 负载下只读事务、YCSB 负载下 中冲突事务(分布比例为 0.5)、TPCC 负载的 NewOrder 事务以及 TPCC 负载的 Payment 事务.

Untitled

Untitled

Untitled

Untitled

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解TCP/IP协议第四篇:数据在网络中传输方式的分类概述

文章目录 前言 一:面向有连接型与面向无连接型 1:大致概念 2:面向有连接型 3:面向无连接型 二:电路交换与分组交换 1:分组交换概念 2:分组交交换过程 三:根据接收端数量分…

免费玩云上大数据--海汼部落实验室

玩大数据遇到的问题 大家好,这次分享一个免费的大数据部署工具,并非是给人家打广告,试过了真的爽。 学习大数据的人都知道,如果用VMware模拟Linux搭建大数据集群的话我们需要很高的内存和硬盘内存,随随便便跑一下mapre…

【云原生】Kubernetes学习笔记

部署 在部署前强调几点 不要使用IPv6, 很多组件都不支持IPv6不要使用最新版本, 最新版本非常不稳定, 甚至可能存在无法运行的bug不要版本更新, 安装后就将版本固定下来, 新的版本可能会引入新功能, 或移除旧功能, 导致Kubernetes无法运行 Kubeadm介绍 K8s是由多个模块构成的…

2023华为杯数模C题——大规模创新类竞赛评审方案研究

B题——大规模创新类竞赛评审方案研究 思路:采用数据分析等手段改进评分算法性能 完成情况(1-2问已经完成) 代码下载 问题一 在每个评审阶段,作品通常都是随机分发的,每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比…

解决因为修改SELINUX配置文件出错导致Faild to load SELinux poilcy无法进入CentOS7系统的问题

一、问题 最近学习Kubernetes,需要设置永久关闭SELINUX,结果修改错了一个SELINUX配置参数,关机重新启动后导致无法进入CentOS7系统,卡在启动进度条界面。 二、解决 多次重启后,在启动日志中发现 Faild to load SELinux poilcy…

简单的自托管书签服务NeonLink

什么是 NeonLink ? NeonLink 是一个简单且开源的自托管书签服务。它是轻量级的,使用最少的依赖项,并且易于通过 Docker 安装。由于系统要求较低,该应用程序非常适合部署在 RaspberryPI 上。 安装 在群晖上以 Docker 方式安装。 …

【ES6】

ES6 1 ES6简介1.1 什么是ES61.2 为什么使用ES6 2 ES6的新增语法2.1 let2.2 const2.3 let、const、var的区别2.4 解构赋值2.4.1 数组解构2.4.2 对象解构 2.5 箭头函数2.6 剩余参数 3 ES6的内置对象扩展3.1 Array的扩展方法3.1.1 扩展运算符(展开语法)3.1.2 构造函数方法&#xf…

Docker 部署 Bitwarden RS 服务

Bitwarden RS 服务是官方 Bitwarden server API 的 Rust 重构版。因为 Bitwarden RS 必须要通过 https 才能访问, 所以在开始下面的步骤之前, 建议先参考 《Ubuntu Nginx 配置 SSL 证书》 配置好域名和 https 访问。 部署 Bitwarden RS 拉取最新版本的 docker.io/vaultwarden…

第一百五十二回 自定义组件综合实例:游戏摇杆三

文章目录 内容回顾优化性能示例代码我们在上一章回中介绍了 如何实现游戏摇杆相关的内容,本章回中将继续介绍这方面的知识.闲话休提,让我们一起Talk Flutter吧。 内容回顾 我们在前面章回中介绍了游戏摇杆的概念以及实现方法,并且通过示例代码演示了实现游戏摇杆的整个过程…

Windows安装cuda和cudnn教程最新版(2023年9月)

文章目录 cudacudnn cuda 查看电脑的cuda最高驱动版本(适用于N卡电脑-Nvidia) winR打开命令行,输入nvidia-smi 右上角cuda -version就是目前支持的最高cuda版本,目前是12.2 nvidia官网下载cuda 下载地址:https://d…

基于eBPF的安卓逆向辅助工具——stackplz

前言 stackplz是一款基于eBPF技术实现的追踪工具,目的是辅助安卓native逆向,仅支持64位进程,主要功能如下: hardware breakpoint 基于pref_event实现的硬件断点功能,在断点处可读取寄存器信息,不会被用户…

C/C++自定义读取ini、cfg配置文件

常见cfg、ini文件如下: [config1] setting192.168.1.1 [config2] setting192.168.1.2 [config3] setting192.168.1.3 示例代码使用 // opt_ini.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> #include "cfg.h"…

短信登录功能如何实现?

简介&#xff1a; 在日常生活中我们登录/注册某些网站/APP是通常可以选择 密码登录和手机号登录。 为什么手机号发送后会有验证码返回呢&#xff1f; 网站如何识别我的验证码是否正确&#xff1f; 如果我的个人网站也想要实现短信登录功能&#xff0c;具体该如何实现&#xff1…

获取文件创建时间

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl Java源码 public void testGetFileTime() {try {String string "E://test.txt";File file new File(string);Path path file.toPath();BasicFileAttributes ba…

如何把利用paddlepaddle导出的json文件转化为yolo或者voc文件

目录 1. 修改源码&#xff0c;让模型能够生成出对于单个图像的标注。 2. 把数据转为yolo格式 3.把yolo格式转化为xml格式 这两天想偷懒&#xff0c;想让模型先在数据上标一遍&#xff0c;然后我再做修正&#xff0c;主要是图个省事。由于我们主要是利用paddle,模型也是基于p…

冒泡排序与选择排序(最low的两兄弟)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言&#xff1a; 在我们的生活中&#xff0c;无处不在用到排序&#xff0c;比如说成绩的排名&#xff0c;淘宝&#xff0c;京东等等商品在各个方面的排序&#xff0c;这样看来一个好的算 法很重要&#xff0c;接下来我们要先…

【刷题-牛客】链表内指定区间反转

链表定区间翻转链表 题目链接题目描述核心思想详细图解代码实现复杂度分析 题目链接 链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com) 题目描述 核心思想 遍历链表的过程中在进行原地翻转 [m,n]翻转区间记作子链表,找到子链表的 起始节点 left 和 终止节点 right记录在…

组队竞赛(int溢出问题)

目录 一、题目 二、代码 &#xff08;一&#xff09;没有注意int溢出 &#xff08;二&#xff09;正确代码 1. long long sum0 2. #define int long long 3. 使用现成的sort函数 一、题目 二、代码 &#xff08;一&#xff09;没有注意int溢出 #include <iostream&g…

自动化测试的定位及一些思考

大家对自动化的理解&#xff0c;首先是想到Web UI自动化&#xff0c;这就为什么我一说自动化&#xff0c;公司一般就会有很多人反对&#xff0c;因为自动化的成本实在太高了&#xff0c;其实自动化是分为三个层面的&#xff08;UI层自动化、接口自动化、单元测试&#xff09;&a…

Sourcetree 无法打开/闪退问题

Sourcetree在某次开机以后无法打开或者是闪退。 Sourcetree是一款Git的可视化图形管理界面,提供了Windows和Mac的免费Git客户端,很方便的管理项目的代码版本 出现问题的环境 win11&#xff0c;sourcTree版本&#xff1a;3.4.12.0 在开始菜单搜索sourcetree&#xff0c;打开…