NS3学习——tcpVegas算法代码详解(2)
NS3学习——tcpVegas算法代码详解(1)-CSDN博客
目录
4.TcpVegas类中成员函数
(5) CongestionStateSet函数
(6) IncreaseWindow函数
1.检查是否启用 Vgas
2.判断是否完成了一个“Vegas 周期”
2.1--if:判断RTT样本数量是否足够
2.2--else:RTT 样本 > 2
2.2.1 if--diff > m_gamma 并且处于慢启动阶段
2.2.2 else if-- diff < m_gamma 并且处于慢启动阶段
2.2.3 else-- 进入拥塞避免阶段
2.2.3.1 --if diff > m_beta
2.2.3.2 --else if diff < m_alpha
2.2.3.3 --else m_alpha < diff < m_beta
2.2.4 --更新慢开始阈值
2.3 --重置RTT计数与最小RTT
3.慢启动阶段判断
(7) GetName函数
(8) GetSsThresh函数
4.TcpVegas类中成员函数
(5) CongestionStateSet函数
void
TcpVegas::CongestionStateSet (Ptr<TcpSocketState> tcb,const TcpSocketState::TcpCongState_t newState)
{NS_LOG_FUNCTION (this << tcb << newState);if (newState == TcpSocketState::CA_OPEN){EnableVegas (tcb);}else{DisableVegas ();}
}
函数作用:根据TCP连接的拥塞状态来启用或者禁用Vegas算法。
函数体:检查传入的newState 参数值是否为:TcpSocketState::CA_OPEN(拥塞避免阶段),若是,则启用Vegas算法,TCP使用该算法来调整拥塞窗口的值;若不是,则停止使用Vegas。
TcpVegas 算法通常在拥塞避免阶段启用,因为此时网络已稳定,Vegas 可以通过动态调整拥塞窗口来更好地利用网络带宽,并避免网络拥塞。
(6) IncreaseWindow函数
void
TcpVegas::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{NS_LOG_FUNCTION (this << tcb << segmentsAcked);if (!m_doingVegasNow){NS_LOG_LOGIC ("Vegas is not turned on, we follow NewReno algorithm.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);return;}if (tcb->m_lastAckedSeq >= m_begSndNxt){ // A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.NS_LOG_LOGIC ("A Vegas cycle has finished, we adjust cwnd once per RTT.");m_begSndNxt = tcb->m_nextTxSequence;if (m_cntRtt <= 2){ // We do not have enough RTT samples, so we should behave like RenoNS_LOG_LOGIC ("We do not have enough RTT samples to do Vegas, so we behave like NewReno.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);}else //m_cntRtt > 2{NS_LOG_LOGIC ("We have enough RTT samples to perform Vegas calculations");uint32_t diff;uint32_t targetCwnd;uint32_t segCwnd = tcb->GetCwndInSegments ();double tmp = m_baseRtt.GetSeconds () / m_minRtt.GetSeconds ();targetCwnd = static_cast<uint32_t> (segCwnd * tmp);NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);NS_ASSERT (segCwnd >= targetCwnd); // implies baseRtt <= minRttdiff = segCwnd - targetCwnd;NS_LOG_DEBUG ("Calculated diff = " << diff);if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh)){NS_LOG_LOGIC ("We are going too fast. We need to slow down and ""change to linear increase/decrease mode.");segCwnd = std::min (segCwnd, targetCwnd + 1);tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else if (tcb->m_cWnd < tcb->m_ssThresh){ // Slow start modeNS_LOG_LOGIC ("We are in slow start and diff < m_gamma, so we ""follow NewReno slow start");TcpNewReno::SlowStart (tcb, segmentsAcked);}else //tcb m_cWnd > m_ssThresh{ // Linear increase/decrease modeNS_LOG_LOGIC ("We are in linear increase/decrease mode");if (diff > m_beta){NS_LOG_LOGIC ("We are going too fast, so we slow down by decrementing cwnd");segCwnd--;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else if (diff < m_alpha){NS_LOG_LOGIC ("We are going too slow, so we speed up by incrementing cwnd");segCwnd++;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else // m_alpha < diff < m_beta{NS_LOG_LOGIC ("We are sending at the right speed");}} //else tcb m_cWnd > m_ssThreshtcb->m_ssThresh = std::max (tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);NS_LOG_DEBUG ("Updated ssThresh = " << tcb->m_ssThresh);} // else m_cntRtt > 2m_cntRtt = 0;m_minRtt = Time::Max ();} //if tcb->m_lastAckedSeq >= m_begSndNxtelse if (tcb->m_cWnd < tcb->m_ssThresh) //tcb->m_lastAckedSeq < m_begSndNxt{TcpNewReno::SlowStart (tcb, segmentsAcked);}
} //IncreaseWindow
函数体逻辑:
1.检查是否启用 Vgas
if (!m_doingVegasNow)
{// If Vegas is not on, we follow NewReno algorithmNS_LOG_LOGIC ("Vegas is not turned on, we follow NewReno algorithm.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);return;
}
如果 m_doingVegasNow 为 false,即 Vegas 算法没有启用,那么执行 NewReno 拥塞控制算法。如果 Vegas 启用,那么执行以下代码:
2.判断是否完成了一个“Vegas 周期”
if (tcb->m_lastAckedSeq >= m_begSndNxt)
{// A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.NS_LOG_LOGIC ("A Vegas cycle has finished, we adjust cwnd once per RTT.");m_begSndNxt = tcb->m_nextTxSequence;
如果 tcb->m_lastAckedSeq(发送方成功接收到的最后一个已确认包的序列号)大于等于 m_begSndNxt( Vegas 周期开始时的发送序列号),则表示当前已经完成了一个 Vegas 周期,并且将 m_begSndNxt 更新为当前的 tcb->m_nextTxSequence,以便下次周期开始时使用新的序列号。执行以下代码:
补:在 Vegas 算法中,一个周期是指发送方根据当前 RTT(往返时延)计算并调整其拥塞窗口(cwnd)的过程。这个周期通常与 RTT 周期同步。
m_lastAckedSeq 的变化非常重要,它帮助判断一个周期是否已经完成。每当接收方成功确认一个数据包,m_lastAckedSeq 会更新,以便发送方能知道哪些数据包已经被接收并得到确认。
在每个周期开始时,m_begSndNxt 会被更新为 当前发送序列号,而这个序列号代表的是 下一个将要发送的数据包的起始字节序列号。
当接收到的 ACK 包的序列号大于等于 m_begSndNxt 时,说明当前周期的所有数据包已经被确认,当前周期结束。
每个周期(每个 RTT)执行一次 IncreaseWindow。
tcb->m_nextTxSequence 是当前即将发送的下一个数据包的序列号。将 m_begSndNxt 更新为 tcb->m_nextTxSequence 是为了确保下一个周期从正确的地方开始。
2.1--if:判断RTT样本数量是否足够
if (m_cntRtt <= 2)
{// We do not have enough RTT samples, so we should behave like RenoNS_LOG_LOGIC ("We do not have enough RTT samples to do Vegas, so we behave like NewReno.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
}
Vegas 需要足够的 RTT 样本才能做出可靠的拥塞窗口调整。
如果 RTT 样本数少于 2(即 m_cntRtt <= 2),它会退回到 NewReno 行为,这时会使用一个简单的慢启动和拥塞避免机制。
如果 RTT 样本 > 2,算法就会根据 Vegas 的逻辑调整cwnd值,同时执行else中的代码:
2.2--else:RTT 样本 > 2
else
{NS_LOG_LOGIC ("We have enough RTT samples to perform Vegas calculations");
计算目标拥塞窗口:
uint32_t diff;
uint32_t targetCwnd;
uint32_t segCwnd = tcb->GetCwndInSegments ();double tmp = m_baseRtt.GetSeconds () / m_minRtt.GetSeconds ();
targetCwnd = static_cast<uint32_t> (segCwnd * tmp);
NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);
NS_ASSERT (segCwnd >= targetCwnd); // implies baseRtt <= minRtt
Vegas 计算目标拥塞窗口(targetCwnd),首先获取当前拥塞窗口大小 segCwnd,然后根据 baseRtt(最小 RTT)和 minRtt(当前窗口内最小 RTT)来计算目标拥塞窗口。
如果 baseRtt 小于等于 minRtt,就可以安全计算目标窗口。
NS_ASSERT (segCwnd >= targetCwnd);
计算公式如下:
计算实际拥塞窗口与目标窗口的差值:
diff = segCwnd - targetCwnd;
NS_LOG_DEBUG ("Calculated diff = " << diff);
计算当前拥塞窗口与目标拥塞窗口之间的差值 diff。这个差值会决定是否需要调整拥塞窗口的大小。
2.2.1 if--diff > m_gamma 并且处于慢启动阶段
当前窗口的差值 diff 大于阈值 m_gamma,并且当前处于慢启动阶段(cwnd 小于 m_ssThresh)
if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh))
{// We are going too fast. We need to slow down and change from// slow-start to linear increase/decrease mode by setting cwnd// to target cwnd. We add 1 because of the integer truncation.NS_LOG_LOGIC ("We are going too fast. We need to slow down and ""change to linear increase/decrease mode.");segCwnd = std::min (segCwnd, targetCwnd + 1);tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);
}
m_alpha 和 m_beta 用于在正常的增速和减速中控制窗口的变化。m_gamma 是一个更大的阈值,通常用于判断网络是否发生了拥塞。
如果 diff > m_gamma,说明当前发送速率比目标速率快得多,且当前处于慢启动阶段。在慢启动阶段,cwnd 会急剧增长。如果在慢启动阶段的拥塞窗口已大于目标值,说明网络可能出现了拥塞的风险。
segCwnd = std::min(segCwnd, targetCwnd + 1):
调整当前cwnd,防止 segCwnd 超过目标窗口 targetCwnd,即避免发送方继续过快地发送数据。
由于 segCwnd 是以“段”为单位的(tcb->GetCwndInSegments()),加1的操作是为了避免整数截断。因为在计算过程中,通常会有一个小数部分,而加 1 可以保证计算结果向上取整,避免由于整数取整带来的问题。
比如,如果目标拥塞窗口是 targetCwnd = 5.4,由于取整的原因,segCwnd 可能被调整为 5,而加 1 后调整为 6。这样可以确保窗口不会太小,从而避免过早减速。
tcb->m_cWnd = segCwnd * tcb->m_segmentSize:
segCwnd 是拥塞窗口的大小(以段为单位)。
tcb->m_segmentSize 是每个 TCP 数据段的大小(字节数)。
segCwnd * tcb->m_segmentSize 得到的是字节级别的拥塞窗口大小,即实际可发送的数据量(以字节为单位)。通过这个公式,可以将段数(segCwnd)转换为字节数(tcb->m_cWnd),并调整发送窗口。
tcb->m_ssThresh = GetSsThresh(tcb, 0):
重新计算并设置新的慢启动阈值,用于控制从慢启动到拥塞避免阶段的过渡。
2.2.2 else if-- diff < m_gamma 并且处于慢启动阶段
当前的拥塞窗口小于慢启动阈值 m_ssThresh 并且 diff 小于 m_gamma
else if (tcb->m_cWnd < tcb->m_ssThresh)
{// Slow start modeNS_LOG_LOGIC ("We are in slow start and diff < m_gamma, so we ""follow NewReno slow start");TcpNewReno::SlowStart (tcb, segmentsAcked);
}
如果当前的拥塞窗口小于慢启动阈值 m_ssThresh,说明此时处于慢启动阶段。此时 diff 小于 m_gamma,表明网络没有拥塞,拥塞窗口仍然可以增长。
此时退回使用 NewReno 算法中的慢启动阶段,通过调用 TcpNewReno::SlowStart 来增加拥塞窗口。
2.2.3 else-- 进入拥塞避免阶段
当前的拥塞窗口大于慢启动阈值,tcb->m_cWnd 大于或等于 tcb->m_ssThresh
进入拥塞避免阶段,通过与目标 targetCwnd 的差值 diff 大小来选择是 增加窗口、减小窗口,还是 保持当前窗口。
else
{// Linear increase/decrease modeNS_LOG_LOGIC ("We are in linear increase/decrease mode");
2.2.3.1 --if diff > m_beta
if (diff > m_beta){// We are going too fast, so we slow downNS_LOG_LOGIC ("We are going too fast, so we slow down by decrementing cwnd");segCwnd--;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);}
- 这表示当前发送速率太快,实际的发送速率(segCwnd)已经超过了目标速率 targetCwnd。
- 为了避免拥塞,减小 segCwnd,即减小拥塞窗口,从而减慢发送速率。
- 减小后的 segCwnd 通过 tcb->m_cWnd = segCwnd * tcb->m_segmentSize; 更新。
- 同时, 通过 GetSsThresh(tcb, 0) 更新慢启动阈值 tcb->m_ssThresh。
2.2.3.2 --else if diff < m_alpha
else if (diff < m_alpha){// We are going too slow, so we speed upNS_LOG_LOGIC ("We are going too slow, so we speed up by incrementing cwnd");segCwnd++;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);}
- 这表示 当前发送速率太慢,实际的发送速率(segCwnd)低于目标速率 targetCwnd。
- 为了加速数据传输,增加 segCwnd,即增大 拥塞窗口。
- 增大的 segCwnd 同样通过 tcb->m_cWnd = segCwnd * tcb->m_segmentSize; 更新。
- 在这种情况下,不需要调整慢启动阈值 tcb->m_ssThresh,因为它不会影响这一阶段的行为。
2.2.3.3 --else m_alpha < diff < m_beta
else
{NS_LOG_LOGIC ("We are sending at the right speed");
}
- 这表示 当前发送速率合适,既不太快也不太慢,数据流量保持在理想状态。
- 不需要对拥塞窗口做出调整,继续维持当前的速率。
2.2.4 --更新慢开始阈值
tcb->m_ssThresh = std::max (tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);
NS_LOG_DEBUG ("Updated ssThresh = " << tcb->m_ssThresh);
- 在(根据拥塞窗口和慢启动阈值大小比较)进行窗口调整之后,根据当前的拥塞窗口 tcb->m_cWnd 更新慢启动阈值(ssthresh)。
- 计算公式 3 * tcb->m_cWnd / 4 是根据 Vegas 算法的设定,确保慢启动阈值不会过小。
- 最终tcb->m_ssThresh 会被设置为 tcb->m_ssThresh 和 3 * tcb->m_cWnd / 4 中的较大值。这是为了确保慢启动阈值有足够的大小,避免在后续过程中频繁进入慢启动阶段。
2.3 --重置RTT计数与最小RTT
m_cntRtt = 0;
m_minRtt = Time::Max ();
- 由于每个周期结束都会重新进行 RTT 测量和窗口调整,所以需要重置 RTT计数(m_cntRtt)和最小RTT(m_minRtt)值。
- m_cntRtt = 0:重置 RTT 样本计数器。
- m_minRtt = Time::Max():将最小 RTT 重置为一个很大的值,确保下一周期开始时能够重新计算最小 RTT。
3.慢启动阶段判断
else if (tcb->m_cWnd < tcb->m_ssThresh)
{TcpNewReno::SlowStart(tcb, segmentsAcked);
}
在周期结束后,检查是否进入了慢启动阶段:
如果当前拥塞窗口 cwnd 小于慢启动阈值 ssThresh,则执行 NewReno 的慢启动算法,快速增长窗口。
注:如果tcb->m_lastAckedSeq < m_begSndNxt,表示当前 Vegas 周期没有结束,那么会进入 else if 判断,如果满足慢启动条件(tcb->m_cWnd < tcb->m_ssThresh),则会执行 NewReno 的慢启动算法。
为什么最后还要判断是否进入慢开始阶段?
如果 cwnd 小于 ssthresh,本应处于慢启动阶段,但由于没有判断 cwnd < ssthresh,程序会直接进入其他模式(如线性增加阶段)。这意味着即使 cwnd 还处于慢启动阶段,程序也会让它变得增长更慢。由于此时 cwnd 还较小,采用线性增长的方式会导致窗口增长太慢,无法迅速利用带宽,从而导致 网络利用率低,吞吐量上升的速度很慢,甚至不能充分利用网络的带宽。也就是说,可能会在不该进入线性增长阶段时就进入该阶段,从而导致 窗口增长速度过慢,降低网络利用率。
这个判断确保了在每个阶段执行适当的窗口调整策略,并帮助算法正确地处理不同网络状态下的拥塞控制。
(7) GetName函数
std::string
TcpVegas::GetName () const
{return "TcpVegas";
}
此函数主要用于标识 TCP 拥塞控制算法的类型,通过调用 GetName(),程序可以知道当前正在使用的是 TCP Vegas 算法。返回一个字符串,"TcpVegas"。
(8) GetSsThresh函数
uint32_t
TcpVegas::GetSsThresh (Ptr<const TcpSocketState> tcb,uint32_t bytesInFlight)
{NS_LOG_FUNCTION (this << tcb << bytesInFlight);return std::max (std::min (tcb->m_ssThresh.Get (), tcb->m_cWnd.Get () - tcb->m_segmentSize), 2 * tcb->m_segmentSize);
}} // namespace ns3
该函数的作用是计算和返回慢启动阈值(ssthresh)。
Ptr<const TcpSocketState>,指向当前连接的 TCP 套接字状态。TcpSocketState 中存储了关于当前 TCP 连接的许多信息,如拥塞窗口(m_cWnd)、慢启动阈值(m_ssThresh)等。
bytesInFlight:这通常表示当前已发送但尚未确认的数据量。这个参数在此函数中没有被直接使用。
tcb->m_ssThresh.Get():当前连接的慢启动阈值。
tcb->m_cWnd.Get() - tcb->m_segmentSize:计算拥塞窗口(cwnd)减去一个数据段的大小,表示如果当前 cwnd 足够大时,应该将 ssthresh 设置为接近这个值。
2 * tcb->m_segmentSize:这是 ssthresh 的最小值,表示即使拥塞窗口较小时,慢启动阈值也不会低于 2 * m_segmentSize。这个值是一个合理的下限,避免在拥塞窗口很小的时候,ssthresh 过小导致性能问题。
返回值:该函数通过 std::max() 和 std::min() 保证返回的 ssthresh 在合理的范围内:
std::min():确保 ssthresh 不会大于 cwnd - segmentSize,即不能超过当前拥塞窗口减去一个数据段的大小。
std::max():确保 ssthresh 不会小于 2 * segmentSize,即在任何情况下 ssthresh 至少为两个数据段大小。
最终返回值就是经过限制的 ssthresh,这是拥塞控制中切换模式的关键值。
相关文章:
NS3学习——tcpVegas算法代码详解(2)
NS3学习——tcpVegas算法代码详解(1)-CSDN博客 目录 4.TcpVegas类中成员函数 (5) CongestionStateSet函数 (6) IncreaseWindow函数 1.检查是否启用 Vgas 2.判断是否完成了一个“Vegas 周期” 2.1--if:判断RTT样本数量是否足够 2.2--e…...
PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程
PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合,具体演示了从数据准备到模型训练和可视化的完整过程。首先,利用一维线性空间生成带噪…...
链原生 Web3 AI 网络 Chainbase 推出 AVS 主网, 拓展 EigenLayer AVS 场景
在 12 月 4 日,链原生的 Web3 AI 数据网络 Chainbase 正式启动了 Chainbase AVS 主网,同时发布了首批 20 个 AVS 节点运营商名单。Chainbase AVS 是 EigenLayer AVS 中首个以数据智能为应用导向的主网 AVS,其采用四层网络架构,其中…...
es 3期 第18节-分页查询使用避坑的一些事
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
linux检测硬盘
通过fdisk 查看显示所有磁盘或闪存的信息 fdisk -l /dev/sd*使用 badlocks检查 linux 硬盘上的坏道/坏块。也可以修复坏道,但仅限于逻辑坏道,物理坏道只能更换硬盘 badblocks -s -v /dev/vdb1 > /badblocks-vdb1.txt tail -f badblocks-vdb1.txt #检…...
Unity3d 基于UGUI和VideoPlayer 实现一个多功能视频播放器功能(含源码)
前言 随着Unity3d引擎在数字沙盘、智慧工厂、数字孪生等场景的广泛应用,视频已成为系统程序中展示时,不可或缺的一部分。在 Unity3d 中,我们可以通过强大的 VideoPlayer 组件和灵活的 UGUI 系统,将视频播放功能无缝集成到用户界面…...
Ubuntu22.04 LTS 安装nvidia显卡驱动
准备跑老师给定的Github上的多模态源码,但是用了这么久ubuntu还没有尝试过安装nvidia驱动,好在也是一次成功,于是记录下来。 借鉴的是Ubuntu22.04安装显卡驱动(高速、避错版)-CSDN博客这篇文章,按照流程来基本没有问题,不过个人觉得有些步骤比较冗余,所以记录下来 主要…...
Linux编程(清华大学出版社2019年1月第1版)第5章课后作业
5.1 对于执行在时间上有重叠的逻辑流,称为并发流,并发流是并发的 并发不并发并发 5.2 几个箭头几个状态转换关系,箭头上写了可能原因。 在就绪状态不会执行指令,不会有IO请求或主动wait的情况,不会有从就绪状态到阻…...
相机雷达外参标定综述“Automatic targetless LiDAR–camera calibration: a survey“
相机雷达外参标定综述--Automatic targetless LiDAR–camera calibration: a survey 前言1 Introduction2 Background3 Automatic targetless LiDAR–camera calibration3.1 Information theory based method(信息论方法)3.1.1 Pairs of point cloud and image attributes(属性…...
JSON 系列之1:将 JSON 数据存储在 Oracle 数据库中
本文为Oracle数据库JSON学习系列的第一篇,讲述如何将JSON文档存储到数据库中,包括了版本为19c和23ai的情形。 19c中的JSON 先来看一下数据库版本为19c时的情形。 创建表colortab,其中color列的长度设为4000。若color的长度需要设为32767&a…...
分布式专题(10)之ShardingSphere分库分表实战指南
一、ShardingSphere产品介绍 Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。Apache ShardingSphere 设计哲学为 Database Plus,旨在…...
支付宝订单码支付
1.订单码支付,首先下载官方网站提供的sdk包到你的项目中。 2.选择控制器复制官方文档的获取二维码相关的代码示例。打开sdk包中v2的index.php文件,这个才是你选择语言的具体代码。 3.引用里面所需要的类文件,文件下载到你的项目中后…...
使用 Django 和 AWS ECR 实现容器化应用的管理
在现代云原生应用的开发和部署中,容器化技术已经成为主流。Amazon Elastic Container Registry (ECR) 是一种完全管理的 Docker 容器注册表服务,可以与 Amazon ECS、EKS 和其他容器服务无缝集成。在这篇文章中,我们将介绍如何使用 Django 和 AWS ECR 实现集成管理,包括创建、更…...
DeepWalk 原理详解
概述: DeepWalk 是一种流行的图嵌入方法,用于学习图结构数据中节点的低维表示。它通过将图的节点视作序列数据,利用自然语言处理中的技术(类似于word2vec算法)来捕捉节点间的关系,可以帮助我们理解和利用图…...
深入理解批量归一化(BN):原理、缺陷与跨小批量归一化(CmBN)
在训练深度神经网络时,批量归一化(Batch Normalization,简称BN)是一种常用且有效的技术,它帮助解决了深度学习中训练过程中的梯度消失、梯度爆炸和训练不稳定等。然而,BN也有一些局限性,特别是在…...
基于Spring Boot的雅苑小区管理系统
一、系统背景与意义 随着信息化技术的快速发展,传统的小区物业管理方式已经难以满足现代居民对于高效、便捷服务的需求。因此,开发一款基于Spring Boot的小区管理系统显得尤为重要。该系统旨在通过信息化手段,实现小区物业管理的智能化、自动…...
物理层知识要点
文章目录 物理层接口的四大特性通信基础编码和调制(1)数字数据编码为数字信号(2)模拟数据编码为数字信号(3)常见调制方式(3)信道的极限容量 多路复用技术数据传输方式物理层下的传输…...
项目里用到了哪些设计模式是怎么使用的?
在软件开发项目中,设计模式是解决特定问题的通用模板或最佳实践。它们提供了一种经过验证的方式来组织代码,使其更易于理解、维护和扩展。下面我将详细介绍一些常见的设计模式及其在项目中的应用方式。 1. 单例模式(Singleton Pattern&#…...
CPU性能篇-CPU 100%如何定位根因-Day 03
1. CPU使用率 1.1 关键指标介绍 user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。nice(通常缩写为 ni),代表低优先级用户态 CPU 时…...
访谈积鼎科技总经理:国产CFD软件发展与未来趋势展望
傅彦国,上海积鼎信息科技有限公司创始人 记者:请傅总介绍下我国流体仿真行业的发展现状是怎样的? 傅彦国:自2018年政府加大了对核心技术自主研发的支持力度,国产CFD软件逐渐步入发展正轨。 首先,从市场规…...
四种自动化测试模型实例及优缺点详解
一、线性测试 1.概念: 通过录制或编写对应应用程序的操作步骤产生的线性脚本。单纯的来模拟用户完整的操作场景。 (操作,重复操作,数据)都混合在一起。 2.优点: 每个脚本相对独立,且不产生…...
数字后端培训项目Floorplan常见问题系列专题续集1
今天继续给大家分享下数字IC后端设计实现floorplan阶段常见问题系列专题。这些问题都是来自于咱们社区IC后端训练营学员提问的问题库。目前这部分问题库已经积累了4年了,后面会陆续分享这方面的问题。 希望对大家的数字后端学习和工作有所帮助。 数字后端项目Floor…...
NVIDIA GPU 内部架构介绍
NVIDIA GPU 架构 NVIDIA GPU 的 SM(Streaming Multiprocessor) 和 GPC(Graphics Processing Cluster) 是 GPU 架构中的关键组成部分。它们决定了 GPU 的计算能力和性能,以下是对这两个参数的详细介绍: 1. …...
[spring]实例化对象(静动态工厂)
在前面文章的例子当中,我们都创建了Bean对象。spring里常用的获取类的实例化对象有几种方式:构造函数获取Bean对象、静态和动态工厂获取Bean对象、实现FactoryBean规范。 因为一些步骤没有什么别的不同,所以我不会重复去讲,届时会…...
【转】arm64架构的银河麒麟系统Kylin的qt安装教程
转自:arm64架构的银河麒麟系统Kylin的qt安装教程_银河麒麟安装qt-CSDN博客 文章目录 前言 一、准备环境 安装C编译器和调试器 二、安装qt、qtcreator 检查是否已经安装过Qt组件 安装Qt组件和Qt creator 检查组件是否安装成功: 三、测试程序运行 报错 Qt…...
C# Main方法 和顶级语句详解
总目录 前言 Main方法 和顶级语句 介绍。 一、Main方法 1. 基本信息 Main 方法是 C# 应用程序的入口点。 Main 方法是应用程序启动后调用的第一个方法。C# 程序中只能有一个入口点。如果多个类包含 Main 方法,必须使用 StartupObject 编译器选项来编译程序&#…...
传输层协议分析头歌
第1关:TCP 包基础 本机使用的IP地址和TCP端口号(用;隔开):192.168.1.102;1161 gaia.cs.umass.edu的IP地址和端口号(用;隔开):128.119.245.12;80 第2关:三次握手 第一次握手,TCP SYN区段的序列号是:232129012 gaia.cs.umass.edu…...
JAVA AOP简单实践(基于SpringBoot)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
重温设计模式--迭代器模式
文章目录 迭代器模式(Iterator Pattern)概述迭代器模式的结构迭代器模式UML图C 代码示例应用场景 迭代器模式(Iterator Pattern)概述 定义: 迭代器模式是一种行为型设计模式,它提供了一种方法来顺序访问一个…...
Unity-Editor扩展GUI基本实现一个可拖拉放的格子列表
短短几百行代码,好吧,又是“参考”了国外的月亮 操作,还真地挺自然的。。。。。。国外的实现有点小牛 拖拉,增加+ 一个Element 鼠标左键长按,可以出提示 鼠标右键,清除Element, 有点小bug,不是很自然地完全清除, using System.Collections; using System.Collecti…...
Android 11添加电容笔电量监测需求
软件平台:Android11 硬件平台:QCS6125 需求:PAD接入电容笔,该笔通过驱动上报坐标及当前电量等数据,即走系统的input通道,需要系统层监测到该硬件数据,这里主要展示电量,对用户显示提…...
迈向AGI——大模型创新体验嘉年华邀请函
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 深度对话,思想碰撞 大模型创新体验嘉年华诚邀您与我们共同见证 智见未来,只等你来 往期精彩文章推荐 关于AI TIME AI TIME源起于2019年,旨在发扬科学思辨精神,…...
VSCode 性能优化指南:提高编码效率,减少资源占用
Visual Studio Code(简称VSCode)是一款广受欢迎的代码编辑器,以其强大的功能和丰富的插件生态系统著称。然而,随着项目规模的扩大和插件数量的增加,VSCode 的性能可能会受到影响。本文将介绍一系列优化措施,…...
如何获取 ABAP 内表中的重复项
要识别 ABAP 内表中的重复项,可以结合使用排序和循环。下面的示例展示了如何查找内部表中的重复条目: DATA: BEGIN OF itab OCCURS 0,field1 TYPE i,field2 TYPE c LENGTH 10,END OF itab,wa LIKE LINE OF itab.* Add sample data to internal table it…...
android 登录界面编写
1、登录页面实现内容 1.实现使用两个EditText输入框输入用户名和密码。 2.使用CheckBox控件记住密码功能。 3.登录时候,验证用户名和密码是否为空。 4.当前CheckBox控件记住密码勾上时,使用SharedPreferences存储用户名和密码。 5.登录时候使用Prog…...
3D-resnet 50 医学3D图像二分类python代码
离上次发布3D-resnet代码时隔两年,最近让AI推荐3D-resnet的文章给我,AI推荐了三篇 其中两篇是我两年前发的,另一篇在这里Resnet3D预训练网络...... 于是决定更新之前代码,供诸位参考1. 可以用cpu或gpu(推荐8G以上&…...
android sqlite 数据库简单封装示例(java)
sqlite 数据库简单封装示例,使用记事本数据库表进行示例。 首先继承SQLiteOpenHelper 使用sql语句进行创建一张表。 public class noteDBHelper extends SQLiteOpenHelper {public noteDBHelper(Context context, String name, SQLiteDatabase.CursorFactory fact…...
项目练习:若依-前端项目的目录结构介绍
文章目录 一、目录截图二、目录讲解 一、目录截图 二、目录讲解 1、首先,我们可以看到,这个VUE项目,只有一个App.vue,所以,它是一个单页面系统。 这个App.vue是根组件,root组件。 2、public目录 在Vue 3.…...
Android 之 List 简述
一、简单创建方式 Android 开发中,列表有很多种类,如ArrayList、LinkedList、List、MutableList等,创建列表的方式如下所示: fun listDemo() {// 使用 listOf 创建不可变的空列表val list listOf<Int>()val list1 listOf…...
CV(6)-SIFT和Hash
前言 仅记录学习过程,有问题欢迎讨论 SIFT:尺度不变特征变换: SIFT提取图像的局部特征,在尺度空间寻找极值点,并提取出其位置、尺度、方向信息。SIFT的应用范围包括物体辨别、机器人地图感知与导航、影像拼接、3D模型建立、手势…...
javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.13.13 not verified:
javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.13.13 not verified: 前言: 之前需求推送数据是采用http:192.168.13.13:8000 后面业务需求修改为 https:192.168.13.13:443 修改后推送数据到第三方报以下异常, https://192.168.13.13:443…...
用Unity做没有热更需求的单机游戏是否有必要使用AssetBundle?
在使用Unity开发没有热更需求的单机游戏时,是否使用AssetBundle(AB包)是一个值得探讨的问题。以下是对此问题的详细分析: 一、AssetBundle的概述 AssetBundle是Unity中用于存储和加载游戏资源的打包文件,可以包含各种…...
WebRTC Simulcast 大小流介绍与优化实践
Simulcast 是 WebRTC 中的一种标准化技术 ,简称大小流。通过 Simulcast,客户端可以同时发送同一视频的多个版本。每个版本都以不同的分辨率和帧率独立编码,带宽较多的拉流端可以接收较高质量的视频流,带宽有限的拉流端则可以接收较…...
软件测试之测试用例
文章目录 测试用例测试用例的编写总结 测试用例 测试用例:描述测试点执行的文档(测试输入、执行条件、预期结果等) 作用 1.测试点能被精准执行 2.便于团队合作测试用例核心内容 用例编号、用例标题、所属模块、优先级、前置条件、测试步骤、测试数据、预期结果 测试用例的编写…...
Redis--通用命令学习
目录 一、引言 二、基础命令 1.set 2.get 3.keys 3.1 keys ? 3.2 keys * 3.3 keys [abe] 3.4 keys [^] 3.5 keys [a-b] 4.exists 5.delete 6.expire 7.ttl 8.type 三、Redis中的过期策略(面试题) 1.惰性删除 2.定期删除 …...
自动控制系统综合与LabVIEW实现
自动控制系统综合是为了优化系统性能,确保其可靠性、稳定性和灵活性。常用方法包括动态性能优化、稳态误差分析、鲁棒性设计等。结合LabVIEW,可以通过图形化编程、高效数据采集与处理来实现系统综合。本文将阐述具体方法,并结合硬件选型提供实…...
一篇文章学会HTML
目录 页面结构 网页基本标签 图像标签 超链接标签 文本链接 图像链接 锚链接 功能链接 列表 有序列表 无序列表 自定义列表 表格 跨列/跨行 表头 媒体元素 视频 音频 网站的嵌套 表单 表单元素 文本框 单选框 多选框 按钮 下拉框 文本域和文件域 表…...
48页PPT|2024智慧仓储解决方案解读
本文概述了智慧物流仓储建设方案的行业洞察、业务蓝图及建设方案。首先,从政策层面分析了2012年至2020年间国家发布的促进仓储业、物流业转型升级的政策,这些政策强调了自动化、标准化、信息化水平的提升,以及智能化立体仓库的建设࿰…...
React Props 完整使用指南
React Props 完整使用指南 1. 类组件中的 Props 1.1 基本使用 // 父组件 class ParentComponent extends React.Component {render() {return (<ChildComponent name"John"age{25}isStudent{true}hobbies{[reading, swimming]}/>);} }// 子组件 class Child…...
金融数据可视化实现
一、设计题目 金融数据可视化 二、设计目的 使学生掌握用Pandas第三方库数据计算、数据分析的知识与能力。Pandas是专门用于数据分析的库,其提供的read_excel()方法可以方便的读取xlsx格式的文件中的数据到Pandas中的DataFrame中。 DataFrame.plot(kindline)&am…...