1.C语言编写的安卓计时器源代码怎么编写?
2.面试官:你先实现个 CountDown 计时器组件吧!
3.UE4 计时器管理 FTimerManager源码剖析
C语言编写的计时器源代码怎么编写?
#include
<time.h>
clock_t
start,end;
在开始计时的地方写:start
=
clock();
在结束的地方写:end
=
clock();
时间等于:t=(end
-
start)/CLOCKS_PER_SEC;
单位是秒
面试官:你先实现个 CountDown 计时器组件吧!
欢迎关注同名公众号《熊的码安猫》,文章会同步更新,卓计也可快速加入前端交流群!时器
最近有个同学在面试时被要求手写一个CountDown 计时器组件,源码dsploit 源码解析但可能是安卓因为之前没有了解过,所以思路上没有那么顺畅,器源过后他询问我应该怎么写(~~哈哈,码安我也没写过~~),卓计于是时器就有了本篇文章,希望本篇文章对你有所帮助!源码!安卓!器源
不难看出,码安要求手写一个CountDown 计时器组件 目的无非考察如下几个方面(~~谁也不知道面试官在想什么~~):
setInterval & setTimeout & requestAnimationFrame
倒计时功能必然需要一个不断执行的异步过程(~~没疑问吧~~),这可以使用运行时环境提供的 API,即 setInterval、omgweb源码setTimeout、requestAnimationFrame,那么到底该选择谁更合适呢?
下面进行逐个分析!
setInterval是什么?
setInterval() 方法会重复调用 一个函数 或 执行一个代码片段,在每次调用之间具有固定的时间间隔,并会返回一个 interval ID 用于标识唯一的时间间隔,可通过调用 clearInterval() 来移除定时器。
共享同一个 ID 池
值得注意的是,setInterval() 和 setTimeout() 是 共享同一个 ID 池 的,所以说 clearInterval() 和 clearTimeout() 在技术上是可 互换使用 的:
但为了避免代码杂乱无章、保证代码的可维护性,还是更推荐使用相互匹配的 clearInterval() 和 clearTimeout()。
延迟限制
当setInterval() 定时器是产生 嵌套使用 时,且 嵌套超过 5 层深度 时:
浏览器这样的行为会使得setInterval() 产生延迟性,原因是 为了减轻嵌套定时器对性能产生的潜在影响。
setTimeout + 递归 更合适?
如果代码逻辑执行时间 可能大于 定时器时间间隔,那么建议你使用 递归调用setTimeout() 的ankidroid 源码方式来实现。
例如,如果你要使用setInterval() 以 5s 轮询服务器,可能因 网络延迟、服务器无响应 或许多其他的问题而导致请求 无法在指定时间内完成,因此可能会出现排队的 XHR 请求 没有按顺序返回 的问题。
setTimeout是什么?
setTimeout() 方法用于设置一个定时器,该定时器在 定时器到期后 执行 一个函数 或 指定的一段代码,并且会返回一个 正整数 的 timeoutID,表示由 setTimeout() 调用创建的定时器的编号,可通过调用 clearTimeout() 来取消定时器。
最大延时值
浏览器内部以 位带符号整数 存储延时,这会导致如果一个延时大于 ms(大约 .8 天) 时会产生溢出,导致定时器将会被 立即执行,这个限制适用于 setInterval() 和 setTimeout()。
延时比指定值更长的原因
有很多因素会导致setTimeout 的 回调函数 执行 比设定的预期值更久:
requestAnimationFrame是什么?
window.requestAnimationFrame() 会告诉浏览器我们希望执行一个 动画,并且要求浏览器在下次 重绘之前 调用指定的回调函数 更新动画,即每 .ms 执行一次回调函数。foundation 源码
回调函数的参数
回调方法在会接收到一个 DOMHighResTimeStamp 参数,它是一个 十进制数,单位为毫秒,最小精度为 1ms(μs)。
同一帧 中的 多个回调函数 都会接受到一个 相同的时间戳,即使在计算上一个回调函数的工作负载期间已经消耗了一些时间,因此要确保总是使用 第一个参数(或其他一些获取当前时间的方法) 来计算动画在一帧中的进度,否则动画在 高刷新率 的屏幕中会 运行得更快。
暂停调用
为了提高性能和电池寿命,在大多数浏览器里,当requestAnimationFrame() 运行在 后台标签页 或 隐藏的 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。
到底选谁?
从以上内容来看,似乎没有一个完美的方案呀,这不是更加大难度了?
莫慌!既然都不完美,那么也要从矮个子中挑个高个子。emmagee源码先不考虑别的,setInterval 和 setTimeout 有一个致命的缺点:
别的不说,就这个缺点就导致使用它们来做倒计时组件不太现实,难不成不允许用户的倒计时超过 天 吗?所以这里选择requestAnimationFrame() + 递归 来实现!
Date.now() & performance.now()
同样的道理,获取当前日期的时间戳也有Date.now() 和 performance.now() 两种方式,又该选谁呢?
Date.now()
是什么?
Date.now() 方法返回自 年 1 月 1 日 :: (UTC) 到当前时间的毫秒数。
时间精度被降低
为了提供针对定时攻击和指纹追踪的保护,Date.now() 的精度可能会根据浏览器的高级设置项目而被取整。
例如,在Firefox 中,默认启用 privacy.reduceTimerPrecision 设置项,在 Firefox 中,默认被取整至 微秒;在 Firefox 中,则被取整至 2 毫秒。
performance.now()
是什么?
performance.now() 方法返回一个 double 类型 的、用于存储 毫秒级 的时间值。
获取当前日期时间戳
performance.now() 主要是用来描述 离散时间点 或 一段时间(两个离散时间点间的时间差),因此它的返回值并不是当 前日期的时间戳,即 performance.now() != Date.now()。
但可以通过换算的方式得到,即
时间精度降低
为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃,在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。
到底该选谁?
好家伙,说白了就还是没有一个完美的选择呗!在这里选Date.now(),毕竟 performance.now() 还得做转换,还有一个原因是 vant-count-down 组件也是用的 Date.now()(~~借鉴借鉴~~)。
实现 CountDown 计时器组件
组件输入 — Props
针对一个CountDown 计时器组件 的 props 应该要包含如下几个内容:
其中时间我们可以直接限制为时间戳,数值类型,当然如果你想支持更多格式,可以自己在写一个方法处理允许外部传入的各种格式,但实际在组件内部使用时必定是保持是同一种类型,因此在这里我们直接限定类型,让外部去进行转换。
组件输出
由于是一个基本的CountDown 计时器组件,我们可以不考虑那么多输出,但至少要向外部暴露如下两个内容:
具体实现
基本思路
效果展示
具体代码
src\components\CountDown\index.vue
src\components\CountDown\composable\useCountDown\index.ts
src\components\CountDown\utils\index.ts
最后
欢迎关注同名公众号《熊的猫》,文章会同步更新,也可快速加入前端交流群!
以上就是一个基本的计时器的实现了,其中肯定有不足之处,不过大家只需要抓住核心思想即可,很多内容都借鉴了 vant-count-down 组件 的实现,感兴趣可以直接去看其对应的源码。
希望本文对你有所帮助!!!
UE4 计时器管理 FTimerManager源码剖析
深入剖析UE4中的计时器管理系统FTimerManager,揭示其核心实现与优化细节。在游戏开发中,精准的计时管理对实现流畅的物理交互和高效的性能优化至关重要。UE4提供了丰富的计时器功能,FTimerManager作为其核心组件,为开发者提供了一套灵活、高效的计时解决方案。
FTimerManager通过FTimerUnifiedDelegate机制,允许开发者在任意时间点绑定逻辑到计时器上。这一设计使得计时逻辑的实现更加灵活,能够根据不同需求选择合适的执行时机。同时,FTimerManager支持计时器的暂停、重启和清除操作,为动态调整计时逻辑提供了便利。
在实现细节上,FTimerManager通过稀疏数组TSparseArray来高效管理计时器列表,避免了传统数组的冗余内存使用,提升了内存管理和性能效率。这种数据结构在插入新计时器时,优先填补空洞,确保了空间使用的优化。
当提及计时器的更新逻辑,FTimerManager在Tick函数中进行轮询处理。这一过程中,FTimerManager不仅维护了活跃计时器的状态,还负责在合适的时间点触发计时逻辑,确保逻辑的执行准确无误。此外,ETimerStatus数据类型用于记录每个计时器的生命周期状态,便于后续操作和状态管理。
总结而言,FTimerManager在UE4中扮演着关键角色,不仅提供了高效、灵活的计时管理功能,还通过优化的数据结构和高效的时间管理机制,显著提升了游戏性能和开发效率。深入研究其源码,不仅能够对UE4的底层逻辑有更深刻的理解,还能启发开发者在自己的项目中进行创新和优化。