1.react源码解析(二)时间管理大师fiber
2.PyTorch 源码解读之 torch.optim:优化算法接口详解
3.JobSchedulerç使ç¨ååç
4.Vue3源码解析(computed-计算属性)
5.深入理解 RxJava2:Scheduler(2)
6.《深入理解react》之调度引擎——Scheduler
react源码解析(二)时间管理大师fiber
React的码详渲染和对比流程在面对大规模节点时,会消耗大量资源,码详影响用户体验。码详为了改进这一情况,码详React引入了Fiber机制,码详成为时间管理大师,码详数字校园 源码平衡了浏览器任务和用户交互的码详响应速度。 Fiber的码详中文翻译为纤程,是码详一种内部更新机制,支持不同优先级的码详任务管理,具备中断与恢复功能。码详每个任务对应于React Element的码详Fiber节点。Fiber允许在每一帧绘制时间(约.7ms)内,码详合理分配计算资源,码详优化性能。码详 相比于React,React引入了Scheduler调度器。当浏览器空闲时,Scheduler会决定是否执行任务。Fiber数据结构具备时间分片和暂停特性,更新流程从递归转变为可中断的循环,通过shouldYield判断剩余时间,灵活调整更新节奏。 Scheduler的关键实现是requestIdleCallback API,它用于高效地处理碎片化时间,提高用户体验。尽管部分浏览器已支持该API,React仍提供了requestIdleCallback polyfill,以确保跨浏览器兼容性。 在Fiber结构中,每个节点包含返回指针(而非直接的父级指针),这个设计使得子节点完成工作后能返回给父级节点。这种机制促进了任务的高效执行。 Fiber的jar支付源码遍历遵循深度优先原则,类似王朝继承制度,确保每一帧内合理分配资源。通过实现深度优先遍历算法,可以构建Fiber树结构,用于渲染和更新DOM元素。 为了深入了解Fiber,可以使用本地环境调试源码。通过创建React项目并配置调试环境,可以观察Fiber节点的结构和行为。了解Fiber的遍历流程和结构后,可以继续实现一个简单的Fiber实例,这有助于理解React渲染机制的核心。 Fiber架构是React的核心,通过时间管理机制优化了性能,使React能够在大规模渲染时保持流畅。了解Fiber的交互流程和遍历机制,有助于深入理解React渲染流程。未来,将详细分析优先级机制、断点续传和任务收集等关键功能,揭示React是如何高效地对比和更新DOM树的。 更多深入学习资源和讨论可参考以下链接: 《React技术揭秘》 《完全理解React Fiber》 《浅谈 React Fiber》 《React Fiber 源码解析》 《走进 React Fiber 的世界》PyTorch 源码解读之 torch.optim:优化算法接口详解
本文深入解读了 PyTorch 中的优化算法接口 torch.optim,主要包括优化器 Optimizer、学习率调整策略 LRScheduler 及 SWA 相关优化策略。以下为详细内容:
Optimizer 是所有优化器的基类,提供了初始化、更新参数、设置初始学习率等基本方法。在初始化优化器时,需要传入模型的可学习参数和超参数。Optimizer 的核心方法包括:
1. 初始化函数:创建优化器时,需指定模型的可学习参数和超参数,如学习率、手机bbs源码动量等。
2. add_param_group:允许为模型的不同可学习参数组设置不同的超参数,以适应不同的学习需求。
3. step:执行一次模型参数更新,需要闭包提供损失函数的梯度信息。
4. zero_grad:在更新参数前,清空参数的梯度信息。
5. state_dict 和 load_state_dict:用于序列化和反序列化优化器的状态,便于保存和加载模型的训练状态。
Optimizer 包括常见的优化器如 SGD、Adagrad、RMSprop 和 Adam,各有特点,适用于不同的应用场景。例如,SGD 适用于简单场景,而 Adam 则在处理大数据集时表现更优。
学习率调节器 lr_scheduler 则负责在训练过程中调整学习率,以适应模型的收敛过程。PyTorch 提供了多种学习率调整策略,如 StepLR、MultiStepLR、ExponentialLR 等,每种策略都有其特点和应用场景,如 StepLR 用于周期性调整学习率,以加速收敛。
SWA(随机权重平均)是一种优化算法,通过在训练过程中计算模型参数的平均值,可以得到更稳定的模型,提高泛化性能。SWA 涉及 AveragedModel 类,用于更新模型的平均参数,以及 update_bn 函数,tree set源码用于在训练过程中更新批量归一化参数。
总结,torch.optim 提供了丰富的优化算法接口,可以根据模型训练的需求灵活选择和配置,以达到最佳的训练效果和泛化性能。通过深入理解这些优化器和学习率调整策略,开发者可以更有效地训练深度学习模型。
JobSchedulerç使ç¨ååç
JobScheduler主è¦ç¨äºå¨æªæ¥æ个æ¶é´ä¸æ»¡è¶³ä¸å®æ¡ä»¶æ¶è§¦åæ§è¡æ项任å¡çæ åµï¼æ¶åçæ¡ä»¶å¯ä»¥æ¯ç½ç»ãçµéãæ¶é´çï¼ä¾å¦æ§è¡ç¹å®çç½ç»ãæ¯å¦åªå¨å çµæ¶æ§è¡ä»»å¡çãJobSchedulerç±»è´è´£å°åºç¨éè¦æ§è¡çä»»å¡åéç»æ¡æ¶ï¼ä»¥å¤å¯¹è¯¥åºç¨Jobçè°åº¦ï¼æ¯ä¸ä¸ªç³»ç»æå¡ï¼å¯ä»¥éè¿å¦ä¸æ¹å¼è·åï¼
JobInfoæ¯ä¼ éç»JobSchedulerç±»çæ°æ®å®¹å¨ï¼å®å°è£ äºé对è°ç¨åºç¨ç¨åºè°åº¦ä»»å¡æéçåç§çº¦æï¼ä¹å¯ä»¥è®¤ä¸ºä¸ä¸ªJobInfo对象对åºä¸ä¸ªä»»å¡ï¼JobInfo对象éè¿JobInfo.Builderå建ãå®å°ä½ä¸ºåæ°ä¼ éç»JobSchedulerï¼
JobInfo.Builderæ¯JobInfoçä¸ä¸ªå é¨ç±»ï¼ç¨æ¥å建JobInfoçBuilderç±»ã
JobServiceæ¯JobScheduleræç»åè°ç端ç¹ï¼JobSchedulerå°ä¼åè°è¯¥ç±»ä¸çonStartJob()å¼å§æ§è¡å¼æ¥ä»»å¡ãå®æ¯ä¸ä¸ªç»§æ¿äºJobServiceçæ½è±¡ç±»ï¼å为系ç»åè°æ§è¡ä»»å¡å 容çç»ç«¯ï¼JobScheduleræ¡æ¶å°éè¿bindService()æ¹å¼æ¥å¯å¨è¯¥æå¡ãå æ¤ï¼ç¨æ·å¿ é¡»å¨åºç¨ç¨åºä¸å建ä¸ä¸ªJobServiceçåç±»ï¼å¹¶å®ç°å ¶onStartJob()çåè°æ¹æ³ï¼ä»¥åå¨AndroidManifest.xmlä¸å¯¹å®æäºå¦ä¸æéï¼
注æå¨AndroidManifest.xmlä¸æ·»å æé
å½ä»»å¡å¼å§æ¶ä¼æ§è¡onStartJob(JobParameters params)æ¹æ³ï¼å¦æè¿åå¼æ¯falseï¼åç³»ç»è®¤ä¸ºè¿ä¸ªæ¹æ³è¿åæ¶ï¼ä»»å¡å·²ç»æ§è¡å®æ¯ãå¦æè¿åå¼æ¯trueï¼é£ä¹ç³»ç»è®¤ä¸ºè¿ä¸ªä»»å¡æ£è¦è¢«æ§è¡ï¼æ§è¡ä»»å¡çéæ å°±è½å¨äºä½ çè©ä¸ãå½ä»»å¡æ§è¡å®æ¯æ¶ä½ éè¦è°ç¨jobFinished(JobParameters params, boolean needsRescheduled)æ¥éç¥ç³»ç»ã
å½ç³»ç»æ¥æ¶å°ä¸ä¸ªåæ¶è¯·æ±æ¶ï¼ç³»ç»ä¼è°ç¨onStopJob(JobParameters params)æ¹æ³åæ¶æ£å¨çå¾ æ§è¡çä»»å¡ãå¾éè¦çä¸ç¹æ¯å¦æonStartJob(JobParameters params)è¿åfalseï¼é£ä¹ç³»ç»åå®å¨æ¥æ¶å°ä¸ä¸ªåæ¶è¯·æ±æ¶å·²ç»æ²¡ææ£å¨è¿è¡çä»»å¡ãæ¢å¥è¯è¯´ï¼onStopJob(JobParameters params)å¨è¿ç§æ åµä¸ä¸ä¼è¢«è°ç¨ã
éè¦æ³¨æçæ¯è¿ä¸ªJob Serviceè¿è¡å¨ä¸»çº¿ç¨ï¼è¿æå³çä½ éè¦ä½¿ç¨å线ç¨ï¼handlerï¼æè ä¸ä¸ªå¼æ¥ä»»å¡æ¥è¿è¡èæ¶çæä½ä»¥é²æ¢é»å¡ä¸»çº¿ç¨ã
Googleå®æ¹çSampleï¼ /googlearchive/android-JobScheduler
JobScheduleræ¯ä¸ä¸ªæ½è±¡ç±»ï¼å®å¨ç³»ç»æ¡æ¶çå®ç°ç±»æ¯android.app.JobSchedulerImpl
æ§è¡çå ¥å£æ¯JobScheduler.schedulerï¼å ¶å®æ¯è°äºJobSchedulerImplä¸çscheduleæ¹æ³ï¼ç¶ååè°äºmBinder.schedule(job)ãè¿ä¸ªmBinderå°±æ¯JobSchedulerServiceï¼éè¿Binderè·¨è¿ç¨è°ç¨JobSchedulerServiceã
æåè°ç¨å°JobSchedulerServiceä¸çscheduleæ¹æ³:
æ¥çåéMSG_CHECK_JOBæ¶æ¯ï¼æ¶æ¯å¤ççå°æ¹æ¯
æ¥çæ§è¡JobHandlerä¸ç maybeRunPendingJobsH æ¹æ³ï¼å¤çç¸åºçä»»å¡
availableContextæ¯JobServiceContextï¼å³ServiceConnectionï¼è¿ä¸ªæ¯è¿ç¨é´é讯ServiceConnectionï¼éè¿è°ç¨availableContext.executeRunnableJob(nextPending)æ¹æ³ï¼ä¼è§¦åè°ç¨onServiceConnectedï¼çå°è¿éåºè¯¥æç½äºï¼onServiceConnectedæ¹æ³ä¸çserviceå°±æ¯Jobserviceï¼éé¢è¿ç¨äºWakeLockéï¼é²æ¢ææºä¼ç ã
æ¥çï¼éè¿Handleråæ¶æ¯ï¼è°ç¨äºhandleServiceBoundH()æ¹æ³ã
ä»ä¸é¢æºç å¯ä»¥çåºï¼æç»æ¯è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
ä»æºç çï¼è®¾ç½®çå 容åºç¨äº JobStatus ï¼ä¾å¦ç½ç»éå¶
èå¨JobSchedulerServiceç±»ï¼ç¸å ³çç¶ææ§å¶å¨å ¶æé å½æ°é:
ä¾å¦ç½ç»æ§å¶ç±»ConnectivityControllerç±»
å½ç½ç»åçæ¹åæ¶ï¼ä¼è°ç¨updateTrackedJobs(userid)æ¹æ³ï¼å¨updateTrackedJobsæ¹æ³ä¸ï¼ä¼å¤æç½ç»æ¯å¦ææ¹åï¼ææ¹åçä¼è°mStateChangedListener.onControllerStateChanged()æ¹æ³ï¼ç¶åè°ç¨äºJobSchedulerServiceç±»ä¸onControllerStateChangedæ¹æ³ï¼
æ¥çä¹æ¯å¤çMSG_CHECK_JOB æ¶æ¯ï¼åä¸æä¸æ ·ï¼æç»è§¦åè°ç¨äºJobServiceä¸çstartJobæ¹æ³ã
JobSchedulerServiceæ¯ä¸ä¸ªç³»ç»æå¡ï¼å³åºè¯¥å¨SystemServerå¯å¨çãé 读SystemServerçæºç ï¼
run æ¹æ³å¦ä¸ï¼
æ¥çç startOtherServices()
å æ¤ï¼å¨è¿éå°±å¯å¨äºJobSchedulerServiceæå¡ã
1. android æ§è½ä¼åJobScheduler使ç¨åæºç åæ
2. Android 9.0 JobScheduler(ä¸) JobSchedulerç使ç¨
3. Android 9.0 JobScheduler(äº) JobScheduleræ¡æ¶ç»æç®è¿°åJobSchedulerServiceçå¯å¨
4. Android 9.0 JobScheduler(ä¸) ä»Jobçå建å°æ§è¡
5. Android 9.0 JobScheduler(å) Job约ææ¡ä»¶çæ§å¶
6. ç解JobScheduleræºå¶
Vue3源码解析(computed-计算属性)
作者:秦志英Vue3计算属性源码解析
在理解了Vue3响应式系统后,我们继续深入剖析其核心组件——计算属性的实现机制。Vue3中的计算属性通过computed函数提供API,让我们通过源码来揭示其内部运作。 在ComputedRefImpl类中,有两个关键私有属性:_value用于缓存计算结果,_dirty用于标记是否需要重新计算。当属性值改变时,会触发trigger函数,遍历并执行依赖的effect函数。如果effect配置了scheduler,那么计算属性的getter并不会立即执行,而是设置_dirty为false,并通知依赖的副作用函数。 构造函数中,我们会包装getter函数为effect,并将其添加到依赖集合中。同时,lazy和scheduler参数控制了计算属性在何时调度。让我们通过一个示例来看计算属性的完整流程:当点击按钮改变testData时,计算属性的更新流程如图所示。总结:计算属性特性
计算属性的主要特性包括:其值依赖于其他属性的更新,但只有在必要时才会重新计算,且通过lazy和scheduler配置实现灵活调度。如果你对Electron感兴趣,不妨关注我们的ubuntuvlc源码编译开源项目Electron Playground,了解更多技术知识。 我们是好未来·晓黑板前端技术团队,持续分享最新技术动态。关注我们:知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园。深入理解 RxJava2:Scheduler(2)
欢迎来到深入理解 RxJava2 系列第二篇,本文基于 RxJava 2.2.0 正式版源码,将探讨 Scheduler 与 Worker 的概念及其实现原理。
Scheduler 与 Worker 在 RxJava2 中扮演着至关重要的角色,它们是线程调度的核心与基石。虽然 Scheduler 的作用较为熟悉,但 Worker 的概念了解的人可能较少。为何在已有 Scheduler 的情况下,还要引入 Worker 的概念呢?让我们继续探讨。
首先,Scheduler 的核心定义是调度 Runnable,支持立即、延时和周期性调用。而 Worker 是任务的最小单元的载体。在 RxJava2 内部实现中,通常一个或多个 Worker 对应一个 ScheduledThreadPoolExecutor 对象,这里暂不深入探讨。
在 RxJava 1.x 中,Scheduler 没有 scheduleDirect/schedulePeriodicallyDirect 方法,只能先创建 Worker,再通过 Worker 来调度任务。这些方法是对 Worker 调度的简化,可以理解为创建一个只能调度一次任务的 Worker 并立即调度该任务。在 Scheduler 基类的源码中,默认实现是直接创建 Worker 并创建对应的 Task(虽然在部分 Scheduler 的覆盖实现上并没有创建 Worker,但可以认为存在虚拟的 Worker)。
一个 Scheduler 可以创建多个 Worker,这两者是一对多的关系,而 Worker 与 Task 也是一对多的关系。Worker 的存在旨在确保两件事:统一调度 Runnable 和统一取消任务。例如,在 observeOn 操作符中,可以通过 Worker 来统一调度和取消一系列的 Runnable。
RxJava2 默认内置了多种 Scheduler 实现,适用于不同场景,这些 Scheduler 都可以在 Schedulers 类中直接获得。以下是两个常用 Scheduler 的源码分析:computation 和 io。
NewThreadWorker 在 computation、io 和 newThread 中都有涉及,下面简单了解一下这个类。NewThreadWorker 与 ScheduledThreadPoolExecutor 之间是一对一的关系,在构造函数中通过工厂方法创建一个 corePoolSize 为 1 的 ScheduledThreadPoolExecutor 对象并持有。
ScheduledThreadPoolExecutor 从 JDK1.5 开始存在,这个类继承于 ThreadPoolExecutor,支持立即、延时和周期性任务。但是注意,在 ScheduledThreadPoolExecutor 中,maximumPoolSize 参数是无效的,corePoolSize 表示最大线程数,且它的队列是无界的。这里不再深入探讨该类,否则会涉及太多内容。
有了这个类,RxJava2 在实现 Worker 时就站在了巨人的肩膀上,线程调度可以直接使用该类解决,唯一的麻烦之处就是封装一层 Disposable 的逻辑。
ComputationScheduler 是计算密集型的 Scheduler,其线程数与 CPU 核心数密切相关。当线程数远超过 CPU 核心数目时,CPU 的时间更多地损耗在了线程的上下文切换。因此,保持最大线程数与 CPU 核心数一致是比较通用的方式。
FixedSchedulerPool 可以看作是固定数量的真正 Worker 的缓存池。确定了 MAX_THREADS 后,在 ComputationScheduler 的构造函数中会创建 FixedSchedulerPool 对象,FixedSchedulerPool 内部会直接创建一个长度为 MAX_THREADS 的 PoolWorker 数组。PoolWorker 继承自 NewThreadWorker,但没有任何额外的代码。
PoolWorker 的使用方法是从池子里取一个 PoolWorker 并返回。但是需要注意,每个 Worker 是独立的,每个 Worker 内部的任务是绑定在这个 Worker 中的。如果按照上述方法暴露 PoolWorker,会出现两个问题:
为了解决上述问题,需要在 PoolWorker 外再包一层 EventLoopWorker。EventLoopWorker 是一个代理对象,它会将 Runnable 代理给 FixedSchedulerPool 中取到的 PoolWorker 来调度,并负责管理通过它创建的任务。当自身被取消时,会将创建的任务全部取消。
与 ComputationScheduler 恰恰相反,IoScheduler 的线程数是无上限的。这是因为 IO 设备的速度远低于 CPU 速度,在等待 IO 操作时,CPU 往往是闲置的。因此,应该创建更多的线程让 CPU 尽可能地利用。当然,并不是线程越多越好,线程数目膨胀到一定程度会影响 CPU 的效率,也会消耗大量的内存。在 IoScheduler 中,每个 Worker 在空置一段时间后就会被清除以控制线程的数目。
CachedWorkerPool 是一个变长并定期清理的 ThreadWorker 的缓存池,内部通过一个 ConcurrentLinkedQueue 维护。和 PoolWorker 类似,ThreadWorker 也是继承自 NewThreadWorker。仅仅是增加了一个 expirationTime 字段,用来标识这个 ThreadWorker 的超时时间。
在 CachedWorkerPool 初始化时,会传入 Worker 的超时时间,目前是写死的 秒。这个超时时间表示 ThreadWorker 闲置后最大存活时间(实际中不保证 秒时被回收)。
IoScheduler 中也存在一个 EventLoopWorker 类,它和 ComputationScheduler 中的作用类似。因为 CachedWorkerPool 是每隔 秒清理一次队列的,所以 ThreadWorker 的存活时间取决于入队的时机。如果一直没有被再次取出,其被实际清理的延迟在 - 秒之间。
熟悉线程的读者会发现,ComputationScheduler 与 IoScheduler 很像某些参数下的 ThreadPoolExecutor。它们对线程的控制外在表现很相似,但实际的线程执行对象不一样。这两者的对比有助于我们更深刻地理解 Scheduler 设计的内在逻辑。
Scheduler 是 RxJava 线程的核心概念,RxJava 基于此屏蔽了 Thread 相关的概念,只与 Scheduler/Worker/Runnable 打交道。
本来计划继续基于 Scheduler 和大家一起探讨 subscribeOn 与 observeOn,但考虑到篇幅问题,这些留待下篇分享。
感谢大家的阅读,欢迎关注笔者的公众号,可以第一时间获取更新,同时欢迎留言沟通。
《深入理解react》之调度引擎——Scheduler
深入理解react
在react 版本发布以来的近两年时间里,许多伙伴都体验到了并发模式带来的爽感,createRoot()的使用让应用有了更流畅的体验。而这一切的核心,便是react执行流中的调度引擎——Scheduler。调度,这个概念在计算机行业中广泛存在,无论是操作系统、浏览器还是大型应用,都离不开调度任务的需求。Scheduler,作为独立的包,不仅可以在react中使用,更可以在任何其他库中发挥作用,其简洁的源码使深入理解react成为可能。
为何需要调度器?首先是为了解决卡顿问题。在js引擎和渲染绘制都在同一线程执行的情况下,如何保证帧的刷新频率不被CPU密集型任务阻塞?其次,react会生成具有优先级的任务,优先级高的任务可能在后面产生,调度器能确保优先级高的任务优先执行,以提升用户体验。
Scheduler通过暴露的方法如unstable_scheduleCallback,可以按照优先级的高低顺序调度任务,并保证异步执行。在实际体验中,我们可以创建工程来测试Scheduler的执行时机,发现它会遵循优先级顺序,优先执行高优先级任务,并在下一个宏任务中异步执行。
源码解析中,小根堆作为关键数据结构,用于维护优先级队列。Scheduler使用小根堆来管理任务,优先级最高的任务始终处于堆顶。优先级的动态调整确保了任务在调度过程中的灵活排序。例如,随着时间推移,新任务的优先级会逐渐提高,使得原有任务在下一个周期中优先执行。
Scheduler的核心逻辑在工作循环中体现,通过合理调度不同优先级的任务,既不阻碍UI绘制,又能高效执行任务。对于大任务,用户可以通过拆分策略,将其划分为多个小任务,以避免阻塞UI,实现流畅的用户体验。
最后,Scheduler在react中扮演着关键角色,通过合理的任务调度,确保应用流畅运行。深入理解Scheduler,将为深入理解react提供坚实的基础。关注专栏,获取更多react相关知识。