基于C++“简单且有效”的“数据库连接池”
前言
- 数据库连接池在开发中应该是很常用的一个组件,他可以很好的节省连接数据库的时间开销;
- 本文基使用C++实现了一个简单的数据库连接池,代码量只有400行左右,但是压力测试效果很好;
- 欢迎收藏 + 关注,本人将会持续更新后端与AI算法有关知识点。
文章目录
- 连接池功能点介绍
- 初始连接量
- 最大连接量
- 最大空闲时间
- 连接超时时间
- 连接池主要包含了以下功能点
- 代码
- 压力测试
MySQL 数据库是基于 C/S 模式的,在每一次访问mysql服务器的时候,都需要建立一个TCP连接,但是,在高并发情况下,大量的 TCP 三次握手、MySQL Server 连接认证、MySQL Server 关闭连接回收资源和 TCP 四次挥手所耗费的性能事件也是很明显的,故设置连接池就是为了减少这一部分的性能损耗。
连接池功能点介绍
初始连接量
表示连接池事先会和 MySQL Serve r创建最小个数的连接,当应用发起 MySQL 访问时,不用再创建和 MySQL Server 新的连接,直接从连接池中获取一个可用的连接即可,使用完成后并不去释放连接,而是把连接再归还到连接池当中。
最大连接量
当并发访问MySQL Server的请求增多时,初始连接量已经不够用了,此时会去创建更多的连接给应用去使用,但是新创建的连接数量上限是maxSize,不能无限制的创建连接。并且当这些连接使用完之后,再次归还到连接池当中来维护。
最大空闲时间
当访问MySQL的并发请求多了以后,连接池里面的连接数量会动态增加,上限是maxSize 个,当这些连接用完会再次归还到连接池当中。如果在指定的时间内这些新增的连接都没有被再次使用过,那么新增加的这些连接资源就要被回收掉,只需要保持初始连接量个连接即可。
连接超时时间
当MySQL的并发请求量过大,连接池中的连接数量已经到达最大数量了,而此时没有空闲的连接可供使用,那么此时应用从连接池获取连接无法成功,它通过阻塞的方式获取连接的时间,如果超过一个时间,那么获取连接失败。
连接池主要包含了以下功能点
- 单例模式设置连接池;
- 向用户提供一个接口,可以从池中拿到一个数据库连接;
- 采用生产者-消费者模式,池用队列作为缓冲区,实现生成连接和拿取连接;
- 采用锁,在创建、拿取连接中进行加锁;
- 采用智能指针管理从队列中获取的连接,并且采用lambda实现智能指针的析构函数,将连接从新放回队列中;
- 设置生产连接、回收连接线程,并且驻留后台,作为守护线程;
- 采用原子变量才记录当前池中的连接数。
创建目录如下:
代码
logger.h
#ifndef PUBLIC_H_
#define PUBLIC_H_#include <iostream>// 作用:封装简单的LOG
#define LOGGER(str) std::cout << "====》" << __LINE__ << " time: " << __TIME__ << " message: " << str << std::endl;#endif // !PUBLIC_H_
connection.h
#ifndef CONNECTION_H_
#define CONNECTION_H_#include <mysql/mysql.h>
#include <ctime>
#include <string>/*
功能:初始化数据库连接释放连接连接数据库查询mysql修改数据库数据刷新/设置空闲时间的起始时间点返回空闲时间
*/class Connection
{
public:// 初始化数据库连接Connection();// 释放连接~Connection();// 连接数据库bool connectionSqlBase(std::string ip, unsigned int port, std::string user, std::string passward, std::string dbName);// 查询mysqlMYSQL_RES* query(std::string sql);// 修改数据库数据bool modify(std::string sql);// 刷新/设置空闲时间的起始时间点void setStartActivateTime();// 返回空闲时间clock_t getActivateTime();
private: MYSQL* m_sqlConn{}; // 连接mysql服务器clock_t m_activateTime; // 记录空闲时间的起始点
};#endif // !CONNECTION_H_
connection.cpp
#include "connection.h"
#include "logger.h"// 初始化数据库连接
Connection::Connection()
{m_sqlConn = mysql_init(nullptr);if(m_sqlConn == nullptr) {LOGGER("mysql init false !!!");return;}
}
// 释放连接
Connection::~Connection()
{mysql_close(m_sqlConn);
}
// 连接数据库
bool Connection::connectionSqlBase(std::string ip, unsigned int port, std::string user, std::string passward, std::string dbName)
{if(nullptr == mysql_real_connect(m_sqlConn, ip.c_str(), user.c_str(), passward.c_str(), dbName.c_str(), port, NULL, 0)) {LOGGER("mysql connects error!!");return false;}return true;
}
// 查询mysql
MYSQL_RES* Connection::query(std::string sql)
{int res = mysql_query(m_sqlConn, sql.c_str());if(0 != res) {LOGGER("sql query false!!!");return nullptr;}return mysql_use_result(m_sqlConn);
}
// 修改数据库数据
bool Connection::modify(std::string sql)
{int res = mysql_query(m_sqlConn, sql.c_str());if(0 != res) {LOGGER("sql update/insert/select false!!!");return false;}return true;
}
// 刷新/设置空闲时间的起始时间点
void Connection::setStartActivateTime()
{m_activateTime = clock();
}
// 返回空闲时间
clock_t Connection::getActivateTime()
{return clock() - m_activateTime;
}
dbConnectionPool.h
#ifndef DBCONNECTION_H_
#define DBCONNECTION_H_#include "connection.h"
#include <mysql/mysql.h>
#include <queue>
#include <string>
#include <condition_variable>
#include <atomic>
#include <memory>// 核心:生产者、消费者模式class DbConnPool
{
public: // 单例模式static DbConnPool* getDbConnPool();// 对外提供接口: 获取连接的数据库,通过智能指针回收std::shared_ptr<Connection> getMysqlConn();// 测试// void test()// {// readConfigurationFile();// }private: // 单例模型:构造函数私有化, 目的:创建最小连接数量DbConnPool();DbConnPool(const DbConnPool&) = delete;DbConnPool operator=(const DbConnPool&) = delete;// 读取配置文件bool readConfigurationFile();// 如果没有Mysql连接了,则产生新连接,这个线程驻留后台(像守护线程一样)void produceNewConn();// 如果队列线程 > initSize, 且空闲时间大于最大空闲时间,则回收void recycleConn();private:// MYSQL连接信息std::string m_ip;unsigned int m_port;std::string m_username;std::string m_password;std::string m_dbname;// 数据库连接池信息int m_initSize;int m_maxSize;int m_maxFreeTime;int m_maxConnTime;// 生产者、消费者共享内存:获取连接std::queue<Connection*> m_connQueue;// 存储当前存储到队列中存储的数量std::atomic_int m_conntionCnt{};// 锁std::mutex m_queueMuetx;// 生产者、消费者:产生连接和取连接std::condition_variable m_cv; // 用于生产线程和消费线程之间的通信
};#endif // !DBCONNECTION_H_
dbConnectionPool.cpp
#include "dbConnectionPool.h"
#include "connection.h"
#include "logger.h"#include <iostream>
#include <cstdio>
#include <cstring>
#include <mutex>
#include <thread>
#include <functional>
#include <chrono>// 创建连接:new,但是拿取连接后是交给shared_ptr// 单例模式
DbConnPool* DbConnPool::getDbConnPool()
{// 最简单的方式:staticstatic DbConnPool pool;return &pool;
}// 对外提供接口: 获取连接的数据库,通过智能指针回收
std::shared_ptr<Connection> DbConnPool::getMysqlConn()
{std::unique_lock<std::mutex> lock(m_queueMuetx);// 判断队列是否为空while(m_connQueue.empty()) {// 队列为空,则等待 最大连接时间, 即这个时候客户端请求连接,但是池里没有连接了,则会等待,如果超过了最大时间,则:连接失败if(std::cv_status::timeout == m_cv.wait_for(lock, std::chrono::seconds(m_maxConnTime))) {// 再次判断是否为空if(m_connQueue.empty()) {LOGGER("no conntion !!!!");return nullptr;}}}/*从队列中获取一个连接,交给**智能指针管理**注意:删除连接有回收线程监控,而这里获取的连接使用完后,需要还给**队列中**,所以**需要重写智能指针的回收函数***/std::shared_ptr<Connection> sp(m_connQueue.front(), [&](Connection* pconn){// 注意,这里需要加锁std::unique_lock<std::mutex> lock(m_queueMuetx);pconn->setStartActivateTime();m_connQueue.push(pconn); // 入队m_conntionCnt++; // +1});// 弹出队列m_connQueue.pop();m_conntionCnt--; // -1return sp;
}// 单例模型:构造函数私有化
DbConnPool::DbConnPool()
{if(readConfigurationFile() == false) {return;}std::unique_lock<std::mutex> lock(m_queueMuetx);for(int i = 0; i < m_maxSize; i++) {Connection* newConn = new Connection();newConn->connectionSqlBase(m_ip, m_port, m_username, m_password, m_dbname);newConn->setStartActivateTime(); // 设置 空闲时间 的起始点m_connQueue.push(newConn); // 入队m_conntionCnt++; // 存储到队列中数据+1}// 开启线程:检查是否需要需要**新创建连接**std::thread produce(std::bind(&DbConnPool::produceNewConn, this));produce.detach(); // 驻留后台// 开启线程,检查是否需要**删除连接**std::thread search(std::bind(&DbConnPool::recycleConn, this));search.detach(); // 驻留后台
}// 读取配置文件
bool DbConnPool::readConfigurationFile()
{FILE* fp = fopen("./mysql.ini", "r");if(fp == nullptr) {LOGGER("mysql.ini open false!!");return false;}char buff[BUFSIZ] = { 0 };while(!feof(fp)) {// clearmemset(buff, 0, sizeof(buff));// 读取fgets(buff, BUFSIZ, fp);std::string str = buff;// 判空if(str.empty()) {continue;}// 截断int idx = str.find('=', 0);if(idx == -1) {continue;}int end = str.find('\n', idx);std::string key = str.substr(0, idx);std::string value = str.substr(idx + 1, end - idx - 1);//std::cout << "key: " << key << " value: " << value << std::endl;if(key == "ip") {m_ip = value;} else if(key == "port") {m_port = atoi(value.c_str());} else if(key == "username") {m_username = value;} else if(key == "password") {m_password = value;} else if(key == "dbname") {m_dbname = value;} else if(key == "initSize") {m_initSize = atoi(value.c_str());} else if(key == "maxSize") {m_maxSize = atoi(value.c_str());} else if(key == "maxFreeTime") {m_maxFreeTime = atoi(value.c_str());} else if(key == "maxConnTime") {m_maxConnTime = atoi(value.c_str());}}std::cout << m_ip << " " << m_port << " " << m_username << " " << m_password << " " << m_dbname << " " << m_initSize << " " << m_maxSize << " " << m_maxFreeTime << " " << m_maxConnTime << std::endl;return true;
}// 如果池里没有Mysql连接了,则产生新连接,这个线程驻留后台(像守护线程一样)
/*
实现思路:设置一个循环:循环检查如果队列不为空,则条件变量一直等待
*/
void DbConnPool::produceNewConn()
{for(;;) {std::unique_lock<std::mutex> lock(m_queueMuetx);while(!m_connQueue.empty()) {m_cv.wait(lock); // 条件变量一直等待}// 这个时候,队列为空,从新创建连接for(int i = 0; i < m_maxSize; i++) {Connection* newConn = new Connection();newConn->setStartActivateTime(); // 刷新时间m_connQueue.push(newConn);m_conntionCnt++; // +1}// 通知等待线程m_cv.notify_all();}
}// 如果队列线程 > initSize, 且空闲时间大于最大空闲时间,则回收
void DbConnPool::recycleConn()
{for(;;) {std::unique_lock<std::mutex> lock(m_queueMuetx);while(m_conntionCnt > m_initSize) {Connection* conn = m_connQueue.front();// 超过最大空闲时间if((static_cast<double>(conn->getActivateTime()) / CLOCKS_PER_SEC) > m_maxFreeTime) {m_connQueue.pop();m_conntionCnt--;delete conn;} else { // 对头没超过,则直接退出break;}}}
}
压力测试
分别插入10000条数据,对没有使用连接池和使用连接池分别进行测试。
#include "dbConnectionPool.h"
#include "connection.h"
#include <iostream>
#include <mysql/mysql.h>
#include <chrono>int main() {auto start = std::chrono::high_resolution_clock::now(); // 获取当前时间点for(int i = 0; i < 10000; i++) {
#if 1DbConnPool* pool = DbConnPool::getDbConnPool();std::shared_ptr<Connection> conn = pool->getMysqlConn();char sql[1024] = { 0 };sprintf(sql, "insert into temp(name, age, sex) values('%s', '%d', '%s');", "yxz", 18, "man");conn->modify(sql);
#elif 0Connection conn;conn.connectionSqlBase("127.0.0.1", 3306, "root", "wy2892586", "test");char sql[1024] = { 0 };sprintf(sql, "insert into temp(name, age, sex) values('%s', '%d', '%s');", "yxz", 18, "man");conn.modify(sql);
#endif}auto end = std::chrono::high_resolution_clock::now(); // 获取结束时间点std::chrono::duration<double, std::milli> duration = end - start; // 计算持续时间,并转换为毫秒std::cout << "Time: " << duration.count() << " ms" << std::endl;return 0;
}
结果如下:
相关文章:
基于C++“简单且有效”的“数据库连接池”
前言 数据库连接池在开发中应该是很常用的一个组件,他可以很好的节省连接数据库的时间开销;本文基使用C实现了一个简单的数据库连接池,代码量只有400行左右,但是压力测试效果很好;欢迎收藏 关注,本人将会…...
vulnhub靶场【kioptrix-4】靶机
前言 靶机:kioptrix-4,IP地址为192.168.1.75,后期IP地址为192.168.10.8 攻击:kali,IP地址为192.168.1.16,后期IP地址为192.168.10.6 都采用VMware虚拟机,网卡为桥接模式 这里的靶机…...
科普:ROC AUC与PR AUC
在评价二分类模型性能时,有许多评价指标,其中,有一对是用面积AUC(Area Under the Curve)做评价的:ROC AUC与PR AUC 本文我们对ROC AUC与PR AUC进行多维度对比分析: 一、定义与核心原理 维度RO…...
服务器IPMI用户名、密码批量检查
背景 大规模服务器部署的时候,少不了较多的网管和监测平台,这些平台会去监控服务器的性能、硬件等指标参数,为了便于管理和控制,则需要给服务器IPMI带外管理添加较多的用户,这就需要对较多的服务器检查所对应的IPMI用…...
51单片机中reg52.h与regx52.h在进行位操作时的不同
reg52.h中不能使用例如 P2_0;这样的定义 而只能使用 P2^0;这样的定义 但是都不可以对位进行直接赋值操作; 而 regx52.h中可以使用 P2_0和P2^0;但是只有使用下划线的才可以对位进行赋值操作 例如P2_0 1; 但不可以是P2^0 1; 在 C 语言中,…...
Apollo Cyber 学习笔记
目录 0 Introduction What Why Advantage 1 Example 2 Concept 3 Flow Chart 4 Module 4.1 Transport 4.1.1 Share Memory 4.1.1.1 Segment 4.1.1.1.1 State 4.1.1.1.2 Block 4.1.1.1.3 Common 4.1.1.2 Notifier 4.1.1.2.1 ConditionNotifier 4.1.1.2.2 Multi…...
【Electron入门】进程环境和隔离
目录 一、主进程和渲染进程 1、主进程(main) 2、渲染进程(renderer) 二、预加载脚本 三、沙盒化 为单个进程禁用沙盒 全局启用沙盒 四、环境访问权限控制:contextIsolation和nodeIntegration 1、contextIsola…...
拉链表介绍
拉链表 是处理 缓慢变化维(SCD) 的一种常用方法,特别适用于需要保留历史记录的场景。以下是拉链表的详细说明及实现方法: 1. 什么是拉链表? 拉链表是一种用于记录维度数据历史变化的表结构,通过 开始时间 …...
Spring Boot 日志配置与常见问题解析(详解)
目录 Spring Boot 日志配置与常见问题解析引言什么是日志?日志的重要性日志使用打印日志 日志框架介绍日志格式的说明⽇志级别日志级别的分类日志级别的使用 Spring Boot 日志配置1. 设置日志级别和格式2. 配置日志收集器3. 查看和分析日志4.日志的持久化5.设置日志…...
-bash: lsof: command not found
一、问题说明 执行如下命令时报错: # lsof |grep deleted > deleted_file -bash: lsof: command not found二、处理方法 # yum -y install lsof安装完成后可成功执行上面的命令。...
PC 端连接安卓手机恢复各类数据:安装、操作步骤与实用指南
软件介绍 这款用于恢复安卓手机数据的软件,虽运行在 PC 端,却专为安卓手机数据恢复打造,使用时得用数据线把手机和电脑连接起来。它的功能相当强大,能帮你找回安卓手机里已删除的短信、联系人、通话记录、文档,还有照…...
ES、OAS、ERP、电子政务、企业信息化(高软35)
系列文章目录 ES、OAS、ERP、电子政务、企业信息化 文章目录 系列文章目录前言一、专家系统(ES)二、办公自动化系统(OAS)三、企业资源规划(ERP)四、典型信息系统架构模型1.政府信息化和电子政务2.企业信息…...
android智能指针android::sp使用介绍
android::sp 是 Android 中的智能指针(Smart Pointer)的实现,用于管理对象的生命周期,避免手动管理内存泄漏等问题。它是 Android libutils 库中重要的一部分,常用于管理继承自 android::RefBase 的对象。 与标准库中…...
推荐一款最新开源,基于AI人工智能UI自动化测试工具!支持自然语言编写脚本!
随着互联网技术的飞速发展,Web应用越来越普及,前端页面也越来越复杂。为了确保产品质量,UI自动化测试成为了开发过程中不可或缺的一环。然而,传统的UI自动化测试工具往往存在学习成本高、维护困难等问题。特别是UI 自动化脚本里往…...
DeepSeek05-大模型WebUI
一、说明: 将DeepSeek部署到前台Web界面的方法主要有以下几种推荐方案,涵盖开源工具、第三方客户端及特定场景适配方案: Open WebUIChatbox AICherry StudioSillyTavern 二、Open WebUI 安装配置教程 特点:Open WebUI 是一个开…...
自然语言处理NLP入门 -- 第八节OpenAI GPT 在 NLP 任务中的应用
在前面的学习中,我们已经了解了如何使用一些经典的方法和模型来处理自然语言任务,如文本分类、命名实体识别等。但当我们需要更强的语言生成能力时,往往会求助于更先进的预训练语言模型。OpenAI 旗下的 GPT 系列模型(如 GPT-3、GP…...
FFmpeg av_read_frame 和iOS系统提供的 AVAudioRecorder 实现音频录制的区别
1. 第一种方式:使用 FFmpeg 的 av_read_frame 特点 底层实现:基于 FFmpeg,这是一个强大的多媒体处理库,直接操作音频流。灵活性:非常灵活,可以处理多种音频格式、编解码器和输入设备。复杂性:需要手动管理音频流、数据包(AVPacket)、内存释放等,代码复杂度较高。跨平…...
【区块链】深入理解区块链中的 Gas 机制
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 深入理解区块链中的 Gas 机制一、Gas 的基本概念1.1 为什么需要 Gas?…...
2020 年英语(一)考研真题 笔记(更新中)
Section I Use of English(完型填空) 原题 Directions:Read the following text. Choose the best word (s) for each numbered blank and mark A, B, C or D on the ANSWER SHEET. (10 points) Even if families are less likely to si…...
mamba_ssm和causal-conv1d详细安装教程
1.前言 Mamba是近年来在深度学习领域出现的一种新型结构,特别是在处理长序列数据方面表现优异。在本文中,我将介绍如何在 Linux 系统上安装并配置 mamba_ssm 虚拟环境。由于官方指定mamba_ssm适用于 PyTorch 版本高于 1.12 且 CUDA 版本大于 11.6 的环境…...
leetcode-442.数组中重复的数据
leetcode-442.数组中重复的数据 文章目录 leetcode-442.数组中重复的数据1.题目描述:数组中重复的数据2.第一次代码提交:(不符合仅使用常量额外空间)3.最终代码提交:只使用常数额外空间、时间复杂度为 O(n) 的做法,即“标记法” 1…...
UniApp 按钮组件 open-type 属性详解:功能、场景与平台差异
文章目录 引言一、open-type 基础概念1.1 核心作用1.2 通用使用模板 二、主流 open-type 值详解2.1 contact - 客服会话功能说明平台支持代码示例 2.2 share - 内容转发功能说明平台支持注意事项 2.3 getUserInfo - 获取用户信息功能说明平台支持代码示例 2.4 getPhoneNumber -…...
Android13修改多媒体默认音量
干就完了! 设置音量为最大音量,修改如下: /framework/base/media/java/android/media/AudioSystem.java/** hide */public static int[] DEFAULT_STREAM_VOLUME new int[] {4, // STREAM_VOICE_CALL7, // STREAM_SYSTEM5, // STREAM_RING-5, // STREAM_MUSIC15, // STREAM…...
【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享
更多银河麒麟操作系统产品及技术讨论,欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer…...
HTTP 请求时传递多部分表单数据
HTTP 请求时传递多部分表单数据(multipart/form-data) --data-raw $------demo11111\r\nContent-Disposition: form-data; name"Filedata"; filename"截屏2025-02-27 15.45.46.png"\r\nContent-Type: image/png\r\n\r\n\r\n------d…...
【Python环境】配置极简描述
241220 241220 241220 Python环境配置 下载Python 稳定版本:Stable Releases【3.12.3】 下载地址:Python Releases for Windows | Python.org. 配环境 注意勾上Add Python 3.x to PATH,然后点“Install Now”即可完成安装。 配置完成&…...
1. HTTP 数据请求
相关资源: 图片素材📎图片素材.zip 接口文档 1. HTTP 数据请求 什么是HTTP数据请求: (鸿蒙)应用软件可以通过(鸿蒙)系统内置的 http 模块 和 Axios,通过 HTTP 协议和服务器进行通讯 学习核心Http请求技术: Http模块 - 属于鸿…...
基于深度学习+NLP豆瓣电影数据爬虫可视化推荐系统
博主介绍:资深开发工程师,从事互联网行业多年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有…...
Apache Spark中的依赖关系与任务调度机制解析
Apache Spark中的依赖关系与任务调度机制解析 在Spark的分布式计算框架中,RDD(弹性分布式数据集)的依赖关系是理解任务调度、性能优化及容错机制的关键。宽依赖(Wide Dependency)与窄依赖(Narrow Dependency)作为两种核心依赖类型,直接影响Stage划分、Shuffle操作及容…...
SEO炼金术(4)| Next.js SEO 全攻略
在上一篇文章 SEO炼金术(3)| 深入解析 SEO 关键要素 中,我们深入解析了 SEO 关键要素,包括 meta 标签、robots.txt、canonical、sitemap.xml 和 hreflang,并探讨了它们在搜索引擎优化(SEO)中的作…...
DeepSeek开源周,第五弹再次来袭,3FS
Fire-Flyer 文件系统(3FS)总结: 一、核心特点 3FS 是一个专为 AI 训练和推理工作负载设计的高性能分布式文件系统,利用现代 SSD 和 RDMA 网络,提供共享存储层,简化分布式应用开发。其主要特点包括…...
conda怎么迁移之前下载的环境包,把python从3.9升级到3.10
克隆旧环境(保留旧环境作为备份) conda create -n cloned_env --clone old_env 在克隆环境中直接升级 Python conda activate cloned_env conda install python3.10 升级 Python 后出现 所有包导入失败 的问题,通常是因为依赖包与新 Pyth…...
一周一个Unity小游戏2D反弹球游戏 - 移动的弹板(鼠标版)
前言 本文将实现控制弹板移动,通过Unity的New Input System,可以支持鼠标移动弹板跟随移动,触控点击跟随移动,并且当弹板移动到边界时,弹板不会移动超过边界之外。 创建移动相关的InputAction 项目模版创建的时候默认会…...
wordpress子分类调用父分类名称和链接的3种方法
专为导航而生,在wordpress模板制作过程中常常会在做breadcrumbs导航时会用到,子分类调用父分类的名称和链接,下面这段简洁的代码,可以完美解决这个问题。 <?php echo get_category_parents( $cat, true, » ); ?…...
使用mermaid查看cursor程序生成的流程图
一、得到cursor生成的流程图文本 cursor写的程序正常运行后,在对话框输入框中输入诸如“请生成扫雷的代码流程图”,然后cursor就把流程图给生成了,但是看到的还是文本的样子,保留这部分内容待用 二、注册一个Mermaid绘图账号 …...
GC垃圾回收介绍及GC算法详解
目录 引言 GC的作用域 什么是垃圾回收? 常见的GC算法 1.引用计数法 2.复制算法 3.标记清除 4.标记整理 小总结 5.分代收集算法 ps:可达性分析算法? 可达性分析的作用 可达性分析与垃圾回收算法的关系 结论 引言 在编程世界中,…...
设计后端返回给前端的返回体
目录 1、为什么要设计返回体? 2、返回体包含哪些内容(如何设计)? 举例 3、总结 1、为什么要设计返回体? 在设计后端返回给前端的返回体时,通常需要遵循一定的规范,以确保前后端交互的清晰性…...
Pytorch为什么 nn.CrossEntropyLoss = LogSoftmax + nn.NLLLoss?
为什么 nn.CrossEntropyLoss LogSoftmax nn.NLLLoss? 在使用 PyTorch 时,我们经常听说 nn.CrossEntropyLoss 是 LogSoftmax 和 nn.NLLLoss 的组合。这句话听起来简单,但背后到底是怎么回事?为什么这两个分开的功能加起来就等于…...
Linux实操——在服务器上直接从百度网盘下载(/上传)文件
Linux Linux实操——在服务器上直接从百度网盘下载(/上传)文件 文章目录 Linux前言一、下载并安装bypy工具二、认证并授权网盘账号三、将所需文件转移至目的文件夹下四、下载文件五、上传文件六、更换绑定的百度云盘账户 前言 最近收到一批很大的数据&…...
【无标题】ABP更换MySql数据库
原因:ABP默认使用的数据库是sqlServer,本地没有安装sqlServer,安装的是mysql,需要更换数据库 ABP版本:9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集,可以看到默认使用的是sqlServer&…...
nuxt常用组件库html-validator应用解析
html-validator 主要用于自动验证nuxt服务器呈现的HTML(SSR和SSG),以检测可能导致水合错误的HTML常见问题,有助于减少水合错误,检测常见的可访问性错误。 安装 npx nuxilatest module add html-validator配置 若自动更新nuxt.config.ts配置文…...
思维训练(算法+技巧)
1.深度优先搜索:暴力求解,适合判断能不能走出迷宫 利用递归,有一个check【】数组来检查该节点是否经过 for循环该节点的邻接节点(存在且没被访问),递归DFS(该节点的某个邻接节点) D…...
AIGC(生成式AI)试用 25 -- 跟着清华教程学习 - DeepSeek+DeepResearch让科研像聊天一样简单
目标:继续学习,以DeepSeek为主 个人理解: - 模型结合,充分发挥各模型的优势 - 关注应用,弱化理论,了解就好 - 多模态:多模态(Multimodality)是指结合多种不同类型的数据…...
Solr中得Core和Collection的作用和关系
Solr中得Core和Collection的作用和关系 一, 总结 在Apache Solr中,Core和Collection 是两个核心概念,他们分别用于单机模式和分布式模式(SolrCloud)中,用于管理和组织数据。 二,Core 定义&am…...
温湿度监控设备融入智慧物联网
当医院的温湿度监控设备融入智慧物联网,将会带来许多新的体验,可以帮助医院温湿度监控设备智能化管理,实现设备之间的互联互通,方便医院对温湿度数据进行统一管理和分析。 添加智慧物联网技术,实现对医院温湿度的实时…...
软件测试的七大误区
随着软件测试对提高软件质量重要性的不断提高,软件测试也不断受到重视。但是,国内软件测试过程的不规范,重视开发和轻视测试的现象依旧存在。因此,对于软件测试的重要性、测试方法和测试过程等方面都存在很多不恰当的认识…...
Mac 版 本地部署deepseek ➕ RAGflow 知识库搭建流程分享(附问题解决方法)
安装: 1、首先按照此视频的流程一步一步进行安装:(macos版)ragflowdeepseek 私域知识库搭建流程分享_哔哩哔哩_bilibili 2、RAGflow 官网文档指南:https://ragflow.io 3、RAGflow 下载地址:https://github.com/infi…...
标记符号“<”和“>”符号被称为“尖括号”或“角括号”
你提到的“<”和“>”符号被称为“尖括号”或“角括号”。它们常用于编程语言中表示类型参数(如泛型)、HTML标签(如<div>)、数学中的不等式(如< 5)等。 好的,我来用通俗的方式解…...
DMA发送全部历史记录数据到串口
背景 博主参与的项目中,有个读取全部历史记录的功能,如果下位机在主程序中将全部历史记录单纯地通过串口传输会比较占用cpu资源,影响主程序中别的功能。最后商量得出以下实现方案: 定义两个发送缓冲区DMATxbuf1和DMATxbuf2&…...
js基础案例
1.弹出警告框,显示Hello JS 2.在页面输出内容(内容在body标签里面) 3.在控制台输出内容 4.js代码是自上而下执行 5.将js代码编写到标签的onclick属性中,当点击时,js代码才会执行 6.将js写到超链接的href属性中…...