当前位置: 首页 > news >正文

LVGL源码学习之渲染、更新过程(3)---绘制和刷写

LVGL版本:8.1

往期回顾:

LVGL源码学习之渲染、更新过程(1)---标记和激活

LVGL源码学习之渲染、更新过程(2)---无效区域的处理

       前文提到,在处理完无效区域后,会得到一个个需要重新绘制的对象,这些对象将在DRAW事件中进行重绘,并将结果写入显示缓存中。

 对象重绘

       来看看draw事件的回调函数都做了什么。在draw主绘制阶段后期绘制阶段,都会进入lv_obj_draw()函数:

//lv_obj.c
static void lv_obj_draw(lv_event_t * e)
{lv_event_code_t code = lv_event_get_code(e);lv_obj_t * obj = lv_event_get_target(e);  //被更新的对象if(code == LV_EVENT_COVER_CHECK) {/*......*/}else if(code == LV_EVENT_DRAW_MAIN) {  //主绘制阶段const lv_area_t * clip_area = lv_event_get_param(e);lv_draw_rect_dsc_t draw_dsc;lv_draw_rect_dsc_init(&draw_dsc);  //初始化绘制描述符/* 是否需要后期再绘制边框 */if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {draw_dsc.border_post = 1;}//把对象的样式填进绘制描述符lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);//被更新对象的坐标范围(包含transform带来的变化)lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);lv_area_t coords;lv_area_copy(&coords, &obj->coords);coords.x1 -= w;coords.x2 += w;coords.y1 -= h;coords.y2 += h;lv_obj_draw_part_dsc_t part_dsc;lv_obj_draw_dsc_init(&part_dsc, clip_area);  //将无效区域填装进来part_dsc.class_p = MY_CLASS;part_dsc.type = LV_OBJ_DRAW_PART_RECTANGLE;part_dsc.rect_dsc = &draw_dsc;part_dsc.draw_area = &coords;part_dsc.part = LV_PART_MAIN;lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);lv_draw_rect(&coords, clip_area, &draw_dsc);  //开始绘制lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);#if LV_DRAW_COMPLEXif(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {/*If the radius is 0 the parent's coordinates will clip anyway*/lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN);if(r != 0) {lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t));lv_draw_mask_radius_init(mp, &obj->coords, r, false);/*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/lv_draw_mask_add(mp, obj + 8);}}
#endif}else if(code == LV_EVENT_DRAW_POST) {  //后期绘制阶段const lv_area_t * clip_area = lv_event_get_param(e);draw_scrollbar(obj, clip_area);#if LV_DRAW_COMPLEXif(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) {lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8);if(param) {lv_draw_mask_free_param(param);lv_mem_buf_release(param);}}
#endif/*If the border is drawn later disable loading other properties*/if(lv_obj_get_style_border_post(obj, LV_PART_MAIN)) {lv_draw_rect_dsc_t draw_dsc;lv_draw_rect_dsc_init(&draw_dsc);draw_dsc.bg_opa = LV_OPA_TRANSP;draw_dsc.outline_opa = LV_OPA_TRANSP;draw_dsc.shadow_opa = LV_OPA_TRANSP;draw_dsc.bg_img_opa = LV_OPA_TRANSP;lv_obj_init_draw_rect_dsc(obj, LV_PART_MAIN, &draw_dsc);lv_coord_t w = lv_obj_get_style_transform_width(obj, LV_PART_MAIN);lv_coord_t h = lv_obj_get_style_transform_height(obj, LV_PART_MAIN);lv_area_t coords;lv_area_copy(&coords, &obj->coords);coords.x1 -= w;coords.x2 += w;coords.y1 -= h;coords.y2 += h;lv_obj_draw_part_dsc_t part_dsc;lv_obj_draw_dsc_init(&part_dsc, clip_area);part_dsc.class_p = MY_CLASS;part_dsc.type = LV_OBJ_DRAW_PART_BORDER_POST;part_dsc.rect_dsc = &draw_dsc;part_dsc.draw_area = &coords;part_dsc.part = LV_PART_MAIN;lv_event_send(obj, LV_EVENT_DRAW_PART_BEGIN, &part_dsc);lv_draw_rect(&coords, clip_area, &draw_dsc);lv_event_send(obj, LV_EVENT_DRAW_PART_END, &part_dsc);}}
}

       主绘制函数lv_draw_rect(),用于搭建主体框架,包括位置、大小,以及使用蒙版(masking)来勾勒圆角(radius)、实现透明度等。

//lv_draw_rect.c
void lv_draw_rect(const lv_area_t * coords, const lv_area_t * clip, const lv_draw_rect_dsc_t * dsc)
{if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return;
#if LV_DRAW_COMPLEXdraw_shadow(coords, clip, dsc);
#endifdraw_bg(coords, clip, dsc);  //绘制背景draw_bg_img(coords, clip, dsc);  //绘制背景图片draw_border(coords, clip, dsc);  //绘制边框(如前面设置border_post,则此处会返回)draw_outline(coords, clip, dsc);  //绘制外轮廓LV_ASSERT_MEM_INTEGRITY();
}

       上面涉及所有的绘制,如背景、图片、边框、外轮廓等,底层都是调用_lv_blend_fill()函数将内容写入显示缓存中。

//lv_draw_blend.c
/*** Fill and area in the display buffer.* @param clip_area 无效区域在当前对象范围的子集(绝对坐标)* @param fill_area 对象的坐标范围(绝对坐标)* @param color 背景颜色* @param mask a mask to apply on the fill (uint8_t array with 0x00..0xff values).*             Relative to fill area but its width is truncated to clip area.* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),*                 LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),*                 LV_MASK_RES_CHANGED: the mask has mixed values* @param opa 背景透明度(0-255)* @param mode blend mode from `lv_blend_mode_t`*/
LV_ATTRIBUTE_FAST_MEM void _lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area,lv_color_t color, lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa,lv_blend_mode_t mode)
{/*Do not draw transparent things*/if(opa < LV_OPA_MIN) return;if(mask_res == LV_DRAW_MASK_RES_TRANSP) return;lv_disp_t * disp = _lv_refr_get_disp_refreshing();lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp);const lv_area_t * disp_area = &draw_buf->area;  //无效区域的坐标lv_color_t * disp_buf = draw_buf->buf_act;if(disp->driver->gpu_wait_cb) disp->driver->gpu_wait_cb(disp->driver);/* 获取实际绘制区域,通常小于等于clip_area(之前传来的无效区域的子集) */lv_area_t draw_area;if(!_lv_area_intersect(&draw_area, clip_area, fill_area)) return;/* draw_area是绝对坐标,需要转化成无效区域内的相对坐标 */lv_area_move(&draw_area, -disp_area->x1, -disp_area->y1);/*Round the values in the mask if anti-aliasing is disabled*/if(mask && disp->driver->antialiasing == 0 && mask) {int32_t mask_w = lv_area_get_width(&draw_area);int32_t i;for(i = 0; i < mask_w; i++)  mask[i] = mask[i] > 128 ? LV_OPA_COVER : LV_OPA_TRANSP;}/* 填充显示缓存disp_buf */if(disp->driver->set_px_cb) {fill_set_px(disp_area, disp_buf, &draw_area, color, opa, mask, mask_res);}else if(mode == LV_BLEND_MODE_NORMAL) {fill_normal(disp_area, disp_buf, &draw_area, color, opa, mask, mask_res);}
#if LV_DRAW_COMPLEXelse {fill_blended(disp_area, disp_buf, &draw_area, color, opa, mask, mask_res, mode);}
#endif
}

刷写显示器

       做完了所有的渲染和绘制,回到最初的更新任务,接下来要做的就是把写好的缓存刷写到显示器上,具体函数为draw_buf_flush()

//lv_refr.c
static void draw_buf_flush(void)
{lv_disp_draw_buf_t * draw_buf = lv_disp_get_draw_buf(disp_refr);lv_color_t * color_p = draw_buf->buf_act;/*Flush the rendered content to the display*/lv_disp_t * disp = _lv_refr_get_disp_refreshing();if(disp->driver->gpu_wait_cb) disp->driver->gpu_wait_cb(disp->driver);/* 双缓冲模式下,需要等待另一个缓冲被释放(相当于上一轮刷写完成),并调用等待函数 */if(draw_buf->buf1 && draw_buf->buf2) {while(draw_buf->flushing) {if(disp_refr->driver->wait_cb) disp_refr->driver->wait_cb(disp_refr->driver);}}draw_buf->flushing = 1;if(disp_refr->driver->draw_buf->last_area && disp_refr->driver->draw_buf->last_part) draw_buf->flushing_last = 1;else draw_buf->flushing_last = 0;  //该标志位只有当最后一片区域的最后一块渲染完成后,才能在刷写过程中置位if(disp->driver->flush_cb) {/* 显示旋转需要进行缓冲区数据转换,该函数内已经包括了刷写功能 */if(disp->driver->rotated != LV_DISP_ROT_NONE && disp->driver->sw_rotate) {draw_buf_rotate(&draw_buf->area, draw_buf->buf_act);}else {call_flush_cb(disp->driver, &draw_buf->area, color_p);  //正常刷写}}if(draw_buf->buf1 && draw_buf->buf2) {  //双缓冲下的缓冲区切换if(draw_buf->buf_act == draw_buf->buf1)draw_buf->buf_act = draw_buf->buf2;elsedraw_buf->buf_act = draw_buf->buf1;}
}

       底层调用注册显示器传入的flush回调函数,刷写到显示器上。

//lv_refr.c
static void call_flush_cb(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
{REFR_TRACE("Calling flush_cb on (%d;%d)(%d;%d) area with %p image pointer", area->x1, area->y1, area->x2, area->y2,(void *)color_p);lv_area_t offset_area = {.x1 = area->x1 + drv->offset_x,.y1 = area->y1 + drv->offset_y,.x2 = area->x2 + drv->offset_x,.y2 = area->y2 + drv->offset_y};drv->flush_cb(drv, &offset_area, color_p);  //刷写硬件的函数
}

       在前面的代码里,根据更新模式不同,采取了不同的刷写方式:

  • 直写模式(direct)下,不分块,但每片区域渲染完毕后都会进行一次刷写;
  • 全刷新模式(full_refresh)下,完成屏幕范围内的重新渲染后,一次性将显示缓存刷写到显示器;
  • 普通模式(normal)下,分块进行刷新,每块完成后都进行一次刷写;

总结

       终于研究完了整个流程,原理倒是不难懂,但代码总感觉不是很漂亮,特别多冗余的代码(为了健壮性考虑,在后面的版本,多少都精简了),比如经常要取无效区域的当前对象坐标区域的交集,这种操作几乎每一层函数调用都在发生,看多了容易理得很乱。

       在测试程序时,特地测试了不同的更新模式和缓冲情况下的性能表现:

  • 全刷新模式下,使用大缓冲(或者显示器大小的缓冲),渲染速度较慢,反而使用小缓冲,速度更快,代价是容易花屏,但整体速度都不如普通模式;
  • 直写模式下,必须使用显示器大小缓冲,否则会报错,速度上略慢于普通模式,但差距很小;
  • 普通模式下,速度最快,也不会有花屏现象,可以适应不同大小的缓冲,只要不是特别大或特别小,性能差距很小;

       对于是否使用单双缓冲,主要取决于内存大小以及刷写方式,如果刷写方式为CPU直接复制内存,则失去了使用双缓冲的意义,双缓存得配合DMA搬运方式才有意义。

相关文章:

LVGL源码学习之渲染、更新过程(3)---绘制和刷写

LVGL版本&#xff1a;8.1 往期回顾&#xff1a; LVGL源码学习之渲染、更新过程(1)---标记和激活 LVGL源码学习之渲染、更新过程(2)---无效区域的处理 前文提到&#xff0c;在处理完无效区域后&#xff0c;会得到一个个需要重新绘制的对象&#xff0c;这些对象将在DRAW事件中…...

CTF-DAY11

[NSSRound#16 Basic]了解过PHP特性吗 题目&#xff1a; <?php error_reporting(0); highlight_file(__FILE__); include("rce.php"); $checker_1 FALSE; $checker_2 FALSE; $checker_3 FALSE; $checker_4 FALSE; $num $_GET[num]; if (preg_match("/…...

手动修改uart16550的FIFO深度?

参考&#xff1a;修改AXI UART D16550 FIFO深度的过程记录 - lmore - 博客园...

Unity按钮事件冒泡

今天unity写程序时&#xff0c;我做了一个透明按钮&#xff0c;没图片&#xff0c;只绑了点击事件&#xff0c;把子对象文字组件也删了&#xff0c;空留一个透明按钮&#xff0c;此时运行时点击按钮是没有反应的&#xff0c;网上的教程说必须指定target graphic&#xff08;目标…...

基于Llama3的开发应用(一):Llama模型的简单部署

Llama模型的简单部署 0 前言1 环境准备1.1 硬件环境1.2 软件环境 2 Meta-Llama-3-8B-Instruct 模型简介2.1 Instruct含义2.2 模型下载 3 简单调用4 FastAPI 部署4.1 通过FastAPI简单部署4.2 测试 5 使用 streamlit 构建简易聊天界面6 总结 0 前言 本系列文章是基于Meta-Llama-…...

人工智能 机器学习期末考试题

自测试卷2 一、选择题 1&#xff0e;下面哪个属性不是NumPy中数组的属性&#xff08; &#xff09;。 A&#xff0e;ndim B&#xff0e;size C&#xff0e;shape D&#xff0e;add 2&#xff0e;一个简单的Series是由&#xff08; &#xff09;的数据组成的。 A&#xff0e;两…...

修改docker为国内源

一、编辑docker配置文件 vi /etc/docker/daemon.json二、配置国内源和修改docker数据目录 {"registry-mirrors":["http://hub-mirror.c.163.com","https://mirrors.tuna.tsinghua.edu.cn","http://mirrors.sohu.com","https://u…...

C++八股 —— vector底层

vector底层为动态数组 类构成 class vector : protected _Vector_base_Vector_base: _M_start&#xff1a;容器元素开始的位置_M_finish&#xff1a;容器元素结束的位置_M_end_of_storage&#xff1a;动态内存最后一个元素的下一个位置 构造函数 无参构造 根据性能优先规则&a…...

postgresql 参数wal_level

wal_level决定多少信息写入到 WAL 中。默认值是replica&#xff0c;它会写入足够的数据以支持WAL归档和复制&#xff0c;包括在后备服务器上运行只读查询。minimal会去掉除从崩溃或者立即关机中进行恢复所需的信息之外的所有记录。最后&#xff0c;logical会增加支持逻辑解码所…...

Lightweight App Alternatives

The tech industry’s business model thrives on constant churn: new features, fancier designs, and heavier apps — not because they’re essential, but because they keep consumers upgrading. Stripping your phone back to basics is an act of tech self-defense.…...

SpringAI--基于MySQL的持久化对话记忆实现

SpringAI–基于MySQL的持久化对话记忆实现 项目源码 对话记忆官方介绍 SpringAI目前提供了一些将对话保存到不同数据源中的实现&#xff0c;比如: InMemoryChatMemory 基于内存存储CassandraChatMemory 在Cassandra中带有过期时间的持久化存储。Neo4jChatMemory 在Neo4j中没…...

【教学类-34-12】20250509(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+数字提示+参考图灰色)

背景介绍 制作了四款异形角拼图,初步实现效果 【教学类-34-10】20250503(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+参考图灰色)-CSDN博客文章浏览阅读1.4k次,点赞46次,收藏15次。【教学类-34-10】20250503(通义万相)4*3蝴蝶拼图(圆形、三角、正方、…...

C++编程语言:标准库:标准库概观(Bjarne Stroustrup)

第30章 标准库概观(Standard-Library Overview) 目录 30.1 引言 30.1.1 标准库设施 30.1.2 设计约束 30.1.3 描述风格 30.2 头文件 30.3 语言支持 30.3.1 对initializer_list的支持 30.3.2 对范围for的支持 30.4 异常处理 30.4.1 异常 30.4.1…...

Springboot+Vue+Mybatis-plus-Maven-Mysql项目部署

目录 VScode 1插件 2快捷键修改 3图标主题设置 4常用设置1 5设置自动换行 6颜色主题 7创建站点 8新建一个html文件 window系统设置 ps 1取色 2测量 3修改单位为像素 4放大图片 5拖动放大之后的图片 6文字大小测量 7测量文字的行高 8矩形选框切图1 9矩形选框…...

【C/C++】C++中noexcept的妙用与性能提升

文章目录 C中noexcept的妙用与性能提升1 什么情况下会抛出异常2 标记noexcept作用3 何时使用noexcept4 无异常行为标记场景5 一句话总结 C中noexcept的妙用与性能提升 在C中&#xff0c;noexcept修饰符用于指示函数不会抛出异常 1 什么情况下会抛出异常 在 C 中&#xff0c;异…...

增强学习(Reinforcement Learning)简介

增强学习&#xff08;Reinforcement Learning&#xff09;简介 增强学习是机器学习的一种范式&#xff0c;其核心目标是让智能体&#xff08;Agent&#xff09;通过与环境的交互&#xff0c;基于试错机制和延迟奖励反馈&#xff0c;学习如何选择最优动作以最大化长期累积回报。…...

如何优化系统启动时间--基于米尔瑞萨MYD-YG2LX开发板

1.概述 MYD-YG2LX采用瑞萨RZ/G2L作为核心处理器&#xff0c;该处理器搭载双核Cortex-A551.2GHzCortex-M33200MHz处理器&#xff0c;其内部集成高性能3D加速引擎Mail-G31 GPU(500MHz)和视频处理单元&#xff08;支持H.264硬件编解码&#xff09;,16位的DDR4-1600 / DDR3L-1333内…...

.Net HttpClient 概述

HttpClient 概述 作用 HttpClient是一个用于发送HTTP请求和接收HTTP响应的类。它提供了一种现代化、灵活和强大的方式来与Web服务进行通信。HttpClient类位于System.Net.Http命名空间下&#xff0c;可以通过NuGet包管理器进行安装。 整体理解 HttpClient是应用程序进程中&am…...

明远智睿SSD2351开发板:仪器仪表与智慧农业的创新利器

在仪器仪表和智慧农业领域&#xff0c;对设备的精度、稳定性和智能化程度有着较高的要求。明远智睿的SSD2351开发板以其独特的优势&#xff0c;成为这两个领域的创新利器。 在仪器仪表方面&#xff0c;SSD2351开发板的四核1.4GHz处理器能够快速处理仪器仪表采集到的各种数据&am…...

VBA -- 学习Day4

数组 创建数组&#xff1a; Dim 数组名&#xff08;数组元素上下角标&#xff09;[As 元素类型] eg. Dim MyArray (1 To 3) As Integer 注意&#xff1a;1.如果不指定元素类型&#xff0c;则是Variant类型 向数组赋值&#xff1a; eg. MyArray(1) 100 MyArray(2) 200…...

Nacos源码—7.Nacos升级gRPC分析四

大纲 5.服务变动时如何通知订阅的客户端 6.微服务实例信息如何同步集群节点 6.微服务实例信息如何同步集群节点 (1)服务端处理服务注册时会发布一个ClientChangedEvent事件 (2)ClientChangedEvent事件的处理源码 (3)集群节点处理数据同步请求的源码 (1)服务端处理服务注册…...

Linux 学习笔记2

Linux 学习笔记2 一、定时任务调度操作流程注意事项 二、磁盘分区与管理添加新硬盘流程磁盘管理命令 三、进程管理进程操作命令服务管理&#xff08;Ubuntu&#xff09; 四、注意事项 一、定时任务调度 操作流程 创建脚本 vim /path/to/script.sh # 编写脚本内容设置可执行权…...

一、每日Github软件分享----QuickGo外链直达工具​

QuickGo 是一款专注于提升网页浏览效率的浏览器扩展工具&#xff0c;其核心功能是自动绕过网站的安全跳转限制&#xff0c;让用户点击外链时无需手动确认&#xff0c;直接跳转至目标页面。以下是详细功能介绍与分析&#xff1a; 一、核心功能与亮点 极速跳转 通过优化浏览器 AP…...

【软件测试】软件缺陷(Bug)的详细描述

目录 一、软件缺陷(Bug) 1.1 缺陷的判定标准 1.2 缺陷的生命周期 1.3 软件缺陷的描述 1.3.1 提交缺陷的要素 1.3.2 Bug 的级别 1.4 如何发现更多的 Bug? 1.5 缺陷的有效管理 1.5.1 缺陷的编写 1.5.2 缺陷管理工具 1.5.2.1 缺陷管理 1.5.2.2 用例管理 一、软件缺陷…...

C++ stl中的list的相关函数用法

文章目录 list的介绍list的使用定义方式 插入和删除迭代器的使用获取元素容器中元素个数和容量的控制其它操作函数 list的使用&#xff0c;首先要包含头文件 #include <list>list的介绍 1.list是一种可以在常数范围内在链表中的任意位置进行插入和删除的序列式容器&…...

Cmd命令大全,从入门到放弃

1、文件和目录操作 dir /p:分页显示目录内容。 dir /w:以单行显示目录内容。 dir /s:显示指定目录及子目录下的所有文件。 dir /b:仅显示文件和目录名称。 dir /a:显示具有特定属性的文件和目录。 cd /d:改变当前驱动器。 pushd:将当前目录压入堆栈,并切换到指定…...

数据同步选择推Push还是拉Pull

数据同步选择“推”&#xff08;Push&#xff09;还是“拉”&#xff08;Pull”&#xff0c;要根据实际场景、系统架构和对实时性、资源消耗、安全性的需求来决定。下面是两种方式的对比分析&#xff0c;帮你更好地判断&#xff1a; 文章目录 推模式&#xff08;Push&#xff…...

Kafka集群加入新Broker节点会发生什么

Kafka集群加入新Broker节点会发生什么 当向现有的Kafka集群添加新的Broker节点时&#xff0c;会触发一系列自动和手动的过程。以下是详细的流程和影响&#xff1a; 自动发生的流程 集群发现与注册 新Broker启动时会向ZooKeeper注册自己加入集群的/brokers/ids路径下其他Broke…...

【LeetCode Solutions】LeetCode 176 ~ 180 题解

CONTENTS LeetCode 176. 第二高的薪水&#xff08;SQL 中等&#xff09;LeetCode 177. 第 N 高的薪水&#xff08;SQL 中等&#xff09;LeetCode 178. 分数排名&#xff08;SQL 中等&#xff09;LeetCode 179. 最大数&#xff08;中等&#xff09;LeetCode 180. 连续出现的数字…...

Sourcetree安装使用的详细教程

Sourcetree 是由 Atlassian 推出的 免费 Git 图形化客户端&#xff0c;支持 Git 和 Mercurial 仓库管理&#xff0c;适用于 Windows 和 macOS。 一、安装教程 1. 下载 官网地址&#xff1a;Sourcetree | Free Git GUI for Mac and Windows 选择你的平台下载安装包&#xff0…...

对比学习入门

Yann Lecun在NIPS 2016上提出了著名的“蛋糕比喻”&#xff1a;如果智能是一个蛋糕&#xff0c;蛋糕上的大部分是无监督学习&#xff08;unsupervised learning&#xff09;&#xff0c;蛋糕上的糖霜是监督学习&#xff08;supervised learning&#xff09;&#xff0c;而蛋糕上…...

Starrocks 的 ShortCircuit短路径

背景 本文基于 Starrocks 3.3.5 本文主要来探索一下Starrocks在FE端怎么实现 短路径&#xff0c;从而加速点查查询速度。 在用户层级需要设置 enable_short_circuit 为true 分析 数据流&#xff1a; 直接到StatementPlanner.createQueryPlan方法&#xff1a; ... OptExpres…...

Windows远程访问Ubuntu的方法

要在Windows上远程访问Ubuntu系统&#xff0c;以下是几种常见的方法&#xff1a; SSH (Secure Shell):通过Windows命令行远程连接到Ubuntu。 在Ubuntu上&#xff0c;确保安装并启用了SSH服务&#xff08;通常可以通过sudo apt update && sudo apt install openssh-serv…...

23种设计模式-行为型模式之模板方法模式(Java版本)

Java 模板方法模式&#xff08;Template Method Pattern&#xff09;详解 &#x1f9e0; 什么是模板方法模式&#xff1f; 模板方法模式是一种行为型设计模式&#xff0c;定义了一个操作中的算法骨架&#xff0c;将一些步骤的实现延迟到子类中。通过模板方法模式&#xff0c;…...

(undone) MIT6.S081 Lec17 VM for APP 学习笔记

url: https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/lec17-virtual-memory-for-applications-frans/17.1-ying-yong-cheng-xu-shi-yong-xu-ni-nei-cun-suo-xu-yao-de-te-xing 17.1 应用程序使用虚拟内存所需要的特性 今天的话题是用户应用程序使用的虚拟内存…...

值拷贝、浅拷贝和深拷贝

✅ 一、基本概念 1. 值拷贝&#xff08;Value Copy&#xff09; 含义&#xff1a;将一个变量的值完整复制到另一个变量中。 对象级别表现&#xff1a;调用的是拷贝构造函数&#xff08;copy constructor&#xff09;。 特点&#xff1a;对基本类型或不含动态资源的对象&…...

JWT原理及工作流程详解

JSON Web Token&#xff08;JWT&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在各方之间安全传输信息。其核心原理是通过结构化、签名或加密的JSON对象实现无状态身份验证和授权。以下是JWT的工作原理和关键组成部分&#xff1a; 1. JWT结构 J…...

广西某建筑用花岗岩矿自动化监测

1. 项目简介 某矿业有限公司成立于2021年&#xff0c;是由某建筑材料有限公司与个人共同出资成立&#xff0c;矿区面积0.4069平方公里&#xff0c;可开采筑用花岗岩、建筑用砂岩。建筑用花岗岩、建筑用砂岩可利用资源量分别为6338.69万吨、303.39万吨&#xff0c;设计生产规模…...

100个思维模型系列更新完毕!

giszz的粉丝们&#xff0c;到今天为止&#xff0c;思维模型专栏已经更新了100期&#xff0c;正式告一段落了。 以下是为你列出的100个思维模型名字&#xff08;部分思维模型可能存在多种表述方式&#xff0c;但核心概念一致&#xff0c;这里尽量涵盖不同领域常见的思维模型&am…...

Bitcoin跨链协议Clementine的技术解析:重构DeFi生态的信任边界

2025年5月2日&#xff0c;比特币Rollup项目Citrea在测试网正式推出跨链协议Clementine&#xff0c;其基于BitVM2编程语言构建的信任最小化桥接技术&#xff0c;被视为解决比特币与DeFi生态融合难题的关键突破。本文从技术背景、核心机制、安全模型、应用场景四大维度&#xff0…...

北斗导航 | RTKLib中重难点技术,公式,代码

Rtklib 一、抗差自适应卡尔曼滤波1. **核心难点**2. **公式与代码实现**二、模糊度固定与LAMBDA算法1. **核心难点**2. **LAMBDA算法实现**3. **部分模糊度固定技术**三、伪距单点定位与误差修正1. **多系统多频点修正**2. **接收机钟差与系统间偏差**四、动态模型与周跳处理1.…...

C++学习之类和对象_1

1. 面向过程与面向对象 C语言是面向过程的&#xff0c;注重过程&#xff0c;通过调用函数解决问题。 比如做番茄炒蛋&#xff1a;买番茄和鸡蛋->洗番茄和打鸡蛋->先炒蛋->把蛋放碟子上->炒番茄->再把蛋倒回锅里->加调料->出锅 而C是面向对象的&#xff…...

Oracle OCP认证考试考点详解083系列14

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 66. 第66题&#xff1a; 题目 解析及答案&#xff1a; 当一个非常大的数据文件被划分为四个部分进行 RMAN 多区段备份时&#xff0c;以下…...

华为欧拉(EulerOS)系统全栈软件部署指南:从 Redis 到 MySQL 实战详解

前言 在国产化操作系统蓬勃发展的背景下&#xff0c;华为欧拉&#xff08;EulerOS&#xff09;凭借其稳定性与安全性&#xff0c;成为企业级服务器部署的重要选择。本文基于官方技术文档与最佳实践&#xff0c;详细梳理 Redis 集群、RabbitMQ、JDK、Tomcat 及 MySQL 在欧拉系统…...

YOLO使用CableInspect-AD数据集实现输电线路缺陷检测

输电线路缺陷检测是一个关键的任务&#xff0c;旨在确保电力传输系统的可靠性和安全性。今天我们使用CableInspect-AD数据集进行训练完成缺陷检测&#xff0c;下载的数据集格式如下&#xff1a; 我们需要经过以下步骤&#xff1a; COCO转YOLO 首先是将COCO格式的数据转换为YO…...

全国青少年信息素养大赛 Python编程挑战赛初赛 内部集训模拟试卷五及详细答案解析

博主推荐 所有考级比赛学习相关资料合集【推荐收藏】1、Python比赛 信息素养大赛Python编程挑战赛 蓝桥杯python选拔赛真题详解...

三个线程 a、b、c 并发运行,b,c 需要 a 线程的数据如何解决

说明&#xff1a; 开发中经常会碰到线程并发&#xff0c;但是后续线程需要等待第一个线程执行完返回结果后&#xff0c;才能再执行后面线程。 如何处理呢&#xff0c;今天就介绍两种方法 1、使用Java自有的API即CountDownLatch&#xff0c;进行实现 思考&#xff1a;CountDown…...

python实现点餐系统

使用python实现点餐系统的增加菜品及价格&#xff0c;删除菜品&#xff0c;查询菜单&#xff0c;点菜以及会员折扣价等功能。 代码&#xff1a; 下面展示一些 内联代码片。 # coding utf-8menu {拍黄瓜: 6, 小炒肉: 28, 西红柿炒蛋: 18, 烤鱼: 30, 红烧肉: 38, 手撕鸡: 45,…...

力扣26——删除有序数组中的重复项

目录 1.题目描述&#xff1a; 2.算法分析&#xff1a; 3.代码展示&#xff1a; 1.题目描述&#xff1a; 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对…...

A2A与MCP定义下,User,Agent,api(tool)间的交互流程图

官方图&#xff1a; 流程图&#xff1a; #mermaid-svg-2smjE8VYydjtLH0p {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2smjE8VYydjtLH0p .error-icon{fill:#552222;}#mermaid-svg-2smjE8VYydjtLH0p .error-tex…...