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

WebSocket 性能优化:从理论到实践

在前四篇文章中,我们深入探讨了 WebSocket 的基础原理、服务端开发、客户端实现和安全实践。今天,让我们把重点放在性能优化上,看看如何构建一个高性能的 WebSocket 应用。我曾在一个直播平台项目中,通过一系列优化措施,将单台服务器的并发连接数从 1 万提升到 10 万。

性能挑战

WebSocket 应用面临的主要性能挑战包括:

  1. 连接管理
  2. 内存使用
  3. CPU 利用率
  4. 网络带宽
  5. 消息处理

让我们逐一解决这些问题。

连接池管理

实现高效的连接池:

// connection-pool.js
class ConnectionPool {constructor(options = {}) {this.options = {maxConnections: 100000,cleanupInterval: 60000,...options}this.connections = new Map()this.groups = new Map()this.stats = new Stats()this.initialize()}// 初始化连接池initialize() {// 启动定期清理this.cleanupTimer = setInterval(() => {this.cleanup()}, this.options.cleanupInterval)// 监控连接数this.stats.gauge('connections.total', () => this.connections.size)this.stats.gauge('connections.active', () => this.getActiveConnections().size)}// 添加连接addConnection(id, connection) {// 检查连接数限制if (this.connections.size >= this.options.maxConnections) {throw new Error('Connection limit reached')}this.connections.set(id, {connection,createdAt: Date.now(),lastActivity: Date.now(),metadata: new Map(),groups: new Set()})this.stats.increment('connections.created')this.emit('connection:added', { id })}// 移除连接removeConnection(id) {const conn = this.connections.get(id)if (!conn) return false// 从所有组中移除conn.groups.forEach(group => {this.removeFromGroup(id, group)})this.connections.delete(id)this.stats.increment('connections.removed')this.emit('connection:removed', { id })return true}// 获取连接getConnection(id) {return this.connections.get(id)}// 更新连接活动时间updateActivity(id) {const conn = this.connections.get(id)if (conn) {conn.lastActivity = Date.now()}}// 添加到组addToGroup(connectionId, group) {const conn = this.connections.get(connectionId)if (!conn) return falseif (!this.groups.has(group)) {this.groups.set(group, new Set())}this.groups.get(group).add(connectionId)conn.groups.add(group)this.stats.increment('groups.members.added')this.emit('group:member:added', { group, connectionId })return true}// 从组中移除removeFromGroup(connectionId, group) {const groupSet = this.groups.get(group)if (!groupSet) return falseconst conn = this.connections.get(connectionId)if (!conn) return falsegroupSet.delete(connectionId)conn.groups.delete(group)// 如果组为空,删除组if (groupSet.size === 0) {this.groups.delete(group)}this.stats.increment('groups.members.removed')this.emit('group:member:removed', { group, connectionId })return true}// 广播到组broadcastToGroup(group, message, excludeId = null) {const groupSet = this.groups.get(group)if (!groupSet) return 0let count = 0groupSet.forEach(id => {if (id !== excludeId) {const conn = this.connections.get(id)if (conn && this.sendMessage(id, message)) {count++}}})this.stats.increment('messages.broadcast', count)return count}// 发送消息sendMessage(id, message) {const conn = this.connections.get(id)if (!conn) return falsetry {conn.connection.send(message)this.stats.increment('messages.sent')this.updateActivity(id)return true} catch (error) {this.stats.increment('messages.failed')return false}}// 获取活跃连接getActiveConnections() {const now = Date.now()const activeConnections = new Map()this.connections.forEach((conn, id) => {if (now - conn.lastActivity <= this.options.activityTimeout) {activeConnections.set(id, conn)}})return activeConnections}// 清理不活跃的连接cleanup() {const now = Date.now()let cleaned = 0this.connections.forEach((conn, id) => {if (now - conn.lastActivity > this.options.activityTimeout) {if (this.removeConnection(id)) {cleaned++}}})if (cleaned > 0) {this.stats.increment('connections.cleaned', cleaned)}return cleaned}// 获取统计信息getStats() {return {connections: {total: this.connections.size,active: this.getActiveConnections().size,groups: this.groups.size},...this.stats.getAll()}}// 关闭连接池shutdown() {clearInterval(this.cleanupTimer)this.connections.forEach((conn, id) => {this.removeConnection(id)})this.emit('shutdown')}
}

内存优化

实现内存管理和监控:

// memory-manager.js
class MemoryManager {constructor(options = {}) {this.options = {heapThreshold: 0.9, // 90% 堆内存使用率阈值gcInterval: 300000, // 5 分钟执行一次 GC...options}this.stats = new Stats()this.initialize()}// 初始化内存管理器initialize() {// 启动定期 GCthis.gcTimer = setInterval(() => {this.runGC()}, this.options.gcInterval)// 监控内存使用this.stats.gauge('memory.heapUsed', () => process.memoryUsage().heapUsed)this.stats.gauge('memory.heapTotal', () => process.memoryUsage().heapTotal)this.stats.gauge('memory.rss', () => process.memoryUsage().rss)}// 运行垃圾回收async runGC() {if (global.gc) {const before = process.memoryUsage()// 运行垃圾回收global.gc()const after = process.memoryUsage()const freed = (before.heapUsed - after.heapUsed) / 1024 / 1024this.stats.increment('memory.gc.runs')this.stats.histogram('memory.gc.freed', freed)return freed}return 0}// 检查内存使用checkMemory() {const { heapUsed, heapTotal } = process.memoryUsage()const usage = heapUsed / heapTotalif (usage > this.options.heapThreshold) {this.emit('memory:warning', { usage })return false}return true}// 获取内存使用报告getMemoryReport() {const usage = process.memoryUsage()return {heapUsed: usage.heapUsed / 1024 / 1024,heapTotal: usage.heapTotal / 1024 / 1024,rss: usage.rss / 1024 / 1024,usage: usage.heapUsed / usage.heapTotal,...this.stats.getAll()}}// 关闭内存管理器shutdown() {clearInterval(this.gcTimer)this.emit('shutdown')}
}

消息队列优化

实现高性能消息队列:

// message-queue.js
class MessageQueue {constructor(options = {}) {this.options = {maxSize: 10000,batchSize: 100,flushInterval: 100,...options}this.queue = new CircularBuffer(this.options.maxSize)this.processing = falsethis.stats = new Stats()this.initialize()}// 初始化队列initialize() {// 启动定期刷新this.flushTimer = setInterval(() => {this.flush()}, this.options.flushInterval)// 监控队列this.stats.gauge('queue.size', () => this.queue.size)this.stats.gauge('queue.capacity', () => this.queue.capacity)}// 添加消息enqueue(message) {if (this.queue.isFull()) {this.stats.increment('queue.dropped')this.emit('queue:full', { message })return false}this.queue.push(message)this.stats.increment('queue.enqueued')// 如果队列达到批处理大小,立即刷新if (this.queue.size >= this.options.batchSize) {setImmediate(() => this.flush())}return true}// 批量添加消息enqueueBatch(messages) {let enqueued = 0for (const message of messages) {if (this.enqueue(message)) {enqueued++}}return enqueued}// 刷新队列async flush() {if (this.processing || this.queue.isEmpty()) return 0this.processing = truelet processed = 0try {// 获取批量消息const batch = []while (batch.length < this.options.batchSize && !this.queue.isEmpty()) {batch.push(this.queue.shift())}if (batch.length > 0) {// 处理批量消息const start = process.hrtime()await this.processBatch(batch)const [seconds, nanoseconds] = process.hrtime(start)processed = batch.lengththis.stats.increment('queue.processed', processed)this.stats.histogram('queue.batch.size', processed)this.stats.histogram('queue.batch.duration',seconds * 1000 + nanoseconds / 1000000)}} catch (error) {this.stats.increment('queue.errors')this.emit('error', error)} finally {this.processing = false}return processed}// 处理批量消息async processBatch(batch) {// 实现具体的批处理逻辑return Promise.all(batch.map(message => this.processMessage(message)))}// 处理单条消息async processMessage(message) {// 实现具体的消息处理逻辑return message}// 获取队列状态getStats() {return {size: this.queue.size,capacity: this.queue.capacity,utilization: this.queue.size / this.queue.capacity,...this.stats.getAll()}}// 关闭队列async shutdown() {clearInterval(this.flushTimer)// 处理剩余消息await this.flush()this.emit('shutdown')}
}

集群扩展

实现集群模式:

// cluster-manager.js
class ClusterManager {constructor(options = {}) {this.options = {workers: os.cpus().length,restartDelay: 1000,...options}this.workers = new Map()this.stats = new Stats()this.initialize()}// 初始化集群initialize() {if (cluster.isMaster) {this.initializeMaster()} else {this.initializeWorker()}}// 初始化主进程initializeMaster() {// 启动工作进程for (let i = 0; i < this.options.workers; i++) {this.createWorker()}// 监听事件cluster.on('exit', (worker, code, signal) => {this.handleWorkerExit(worker, code, signal)})// 监控工作进程this.stats.gauge('cluster.workers', () => this.workers.size)}// 初始化工作进程initializeWorker() {// 实现工作进程逻辑process.on('message', message => {this.handleMessage(message)})}// 创建工作进程createWorker() {const worker = cluster.fork()this.workers.set(worker.id, {worker,startTime: Date.now(),restarts: 0})worker.on('message', message => {this.handleWorkerMessage(worker, message)})this.stats.increment('cluster.workers.created')this.emit('worker:created', { workerId: worker.id })return worker}// 处理工作进程退出handleWorkerExit(worker, code, signal) {const info = this.workers.get(worker.id)if (!info) returnthis.workers.delete(worker.id)this.stats.increment('cluster.workers.exited')// 记录退出原因this.emit('worker:exit', {workerId: worker.id,code,signal,uptime: Date.now() - info.startTime})// 重启工作进程setTimeout(() => {if (this.workers.size < this.options.workers) {this.createWorker()}}, this.options.restartDelay)}// 处理工作进程消息handleWorkerMessage(worker, message) {switch (message.type) {case 'stats':this.updateWorkerStats(worker.id, message.data)breakcase 'error':this.handleWorkerError(worker.id, message.data)breakdefault:this.emit('worker:message', {workerId: worker.id,message})}}// 更新工作进程统计updateWorkerStats(workerId, stats) {const info = this.workers.get(workerId)if (info) {info.stats = stats}}// 处理工作进程错误handleWorkerError(workerId, error) {this.stats.increment('cluster.workers.errors')this.emit('worker:error', {workerId,error})}// 获取集群状态getStats() {const workerStats = {}this.workers.forEach((info, id) => {workerStats[id] = {uptime: Date.now() - info.startTime,restarts: info.restarts,...info.stats}})return {workers: {total: this.workers.size,target: this.options.workers,stats: workerStats},...this.stats.getAll()}}// 关闭集群shutdown() {if (cluster.isMaster) {// 关闭所有工作进程this.workers.forEach((info, id) => {info.worker.kill()})}this.emit('shutdown')}
}

性能监控

实现性能监控系统:

// performance-monitor.js
class PerformanceMonitor {constructor(options = {}) {this.options = {sampleInterval: 1000,historySize: 3600,...options}this.metrics = new Map()this.history = new CircularBuffer(this.options.historySize)this.stats = new Stats()this.initialize()}// 初始化监控器initialize() {// 启动采样this.sampleTimer = setInterval(() => {this.sample()}, this.options.sampleInterval)// 监控系统指标this.monitor('cpu', () => {const usage = process.cpuUsage()return (usage.user + usage.system) / 1000000})this.monitor('memory', () => {const usage = process.memoryUsage()return usage.heapUsed / 1024 / 1024})this.monitor('eventLoop', () => {return this.measureEventLoopLag()})}// 监控指标monitor(name, collector) {this.metrics.set(name, {collector,values: new CircularBuffer(this.options.historySize)})}// 采样数据sample() {const timestamp = Date.now()const sample = {timestamp,metrics: {}}this.metrics.forEach((metric, name) => {try {const value = metric.collector()metric.values.push(value)sample.metrics[name] = value} catch (error) {this.stats.increment('monitor.errors')}})this.history.push(sample)this.stats.increment('monitor.samples')this.emit('sample', sample)}// 测量事件循环延迟measureEventLoopLag() {return new Promise(resolve => {const start = process.hrtime()setImmediate(() => {const [seconds, nanoseconds] = process.hrtime(start)resolve(seconds * 1000 + nanoseconds / 1000000)})})}// 获取指标统计getMetricStats(name, duration = 3600000) {const metric = this.metrics.get(name)if (!metric) return nullconst values = metric.values.toArray()const now = Date.now()const filtered = values.filter(v => now - v.timestamp <= duration)return {current: values[values.length - 1],min: Math.min(...filtered),max: Math.max(...filtered),avg: filtered.reduce((a, b) => a + b, 0) / filtered.length,p95: this.calculatePercentile(filtered, 95),p99: this.calculatePercentile(filtered, 99)}}// 计算百分位数calculatePercentile(values, percentile) {const sorted = [...values].sort((a, b) => a - b)const index = Math.ceil((percentile / 100) * sorted.length) - 1return sorted[index]}// 获取性能报告getReport(duration = 3600000) {const report = {timestamp: Date.now(),metrics: {}}this.metrics.forEach((metric, name) => {report.metrics[name] = this.getMetricStats(name, duration)})return {...report,...this.stats.getAll()}}// 关闭监控器shutdown() {clearInterval(this.sampleTimer)this.emit('shutdown')}
}

最佳实践

  1. 连接管理

    • 使用连接池管理连接
    • 实现自动清理机制
    • 控制最大连接数
  2. 内存优化

    • 实现内存监控
    • 定期进行垃圾回收
    • 控制内存使用阈值
  3. 消息处理

    • 使用消息队列
    • 实现批量处理
    • 控制消息大小
  4. 集群扩展

    • 使用多进程架构
    • 实现负载均衡
    • 处理进程通信
  5. 性能监控

    • 监控系统指标
    • 收集性能数据
    • 设置告警机制

写在最后

通过这篇文章,我们深入探讨了如何优化 WebSocket 应用的性能。从连接管理到内存优化,从消息处理到集群扩展,我们不仅关注了理论知识,更注重了实际应用中的性能挑战。

记住,性能优化是一个持续的过程,需要不断监控和改进。在实际开发中,我们要根据具体场景选择合适的优化策略,确保应用能够高效稳定地运行。

如果觉得这篇文章对你有帮助,别忘了点个赞 👍

相关文章:

WebSocket 性能优化:从理论到实践

在前四篇文章中,我们深入探讨了 WebSocket 的基础原理、服务端开发、客户端实现和安全实践。今天,让我们把重点放在性能优化上,看看如何构建一个高性能的 WebSocket 应用。我曾在一个直播平台项目中,通过一系列优化措施,将单台服务器的并发连接数从 1 万提升到 10 万。 性能挑…...

我用AI学Android Jetpack Compose之入门篇(2)

我跑成功了第一个Compose应用&#xff0c;但我还是有很多疑问&#xff0c;请人工智能来解释一下吧。答案来自 通义千问 文章目录 1.请解释一下Compose项目的目录结构。根目录模块目录&#xff08;通常是app&#xff09;app/build.gradleapp/src/mainapp/src/main/uiapp/src/ma…...

以太网协议在汽车应用中的动与静

为了让网络中的设备能够随时或随地接入网络或离开网络&#xff0c;做到&#xff1a;接入时无需多余的配置就能和其他设备互相通信&#xff1b;离开时又不会导致设备或网络崩溃。以太网从物理层到协议层展现出多方面的灵活性&#xff0c;&#xff0c;使其成为连接各种设备和系统…...

【C语言】_指针与数组

目录 1. 数组名的含义 1.1 数组名与数组首元素的地址的联系 1.3 数组名与首元素地址相异的情况 2. 使用指针访问数组 3. 一维数组传参的本质 3.1 代码示例1&#xff1a;函数体内计算sz&#xff08;sz不作实参传递&#xff09; 3.2 代码示例2&#xff1a;sz作为实参传递 3…...

Selenium 的四种等待方式及使用场景

Selenium 的四种等待方式及使用场景 隐式等待&#xff08;Implicit Wait&#xff09;显式等待&#xff08;Explicit Wait&#xff09;自定义等待&#xff08;Custom Wait&#xff09;固定等待&#xff08;Sleep&#xff09; 1. 隐式等待 定义&#xff1a; 隐式等待是为 WebD…...

React知识盲点——组件通信、性能优化、高级功能详解(大纲)

组件通信 React 组件通信详解 在 React 中&#xff0c;组件通信是一个核心概念&#xff0c;主要指的是如何让不同的组件共享和传递数据。React 提供了多种机制来实现组件间的数据传递和状态共享。以下是几种常见的组件通信方式&#xff0c;包括&#xff1a;父子组件通信&…...

Vue 按键生成多个表单

本文通过 vueele&#xff0c;通过循环ref的方法生成多个表单,代码如下&#xff1a; <template><div><el-button click"addText" style"margin: 15px 0; ">添加字段</el-button><div v-for"item, index in dataList"…...

网络安全:交换机技术

单播&#xff0c;组播广播 单播(unicast): 是指封包在计算机网络的传输中&#xff0c;目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛&#xff0c;通常所使用的网络协议或服务大多采用单播传输&#xff0c;例如一切基于TCP的协议。组播(multicast): 也叫多播&am…...

Flask 快速入门

1. Flask 简介 1.1 什么是 Flask Flask 是一个用 Python 编写的轻量级 Web 框架&#xff0c;被誉为 微框架。它提供基础功能&#xff0c;如路由、请求处理和模板引擎&#xff0c;但不强迫开发者使用特定库或工具&#xff0c;赋予开发人员高度的自由选择权&#xff0c;以满足不…...

C#设计模式(行为型模式):备忘录模式,时光倒流的魔法

C#设计模式&#xff1a;备忘录模式&#xff0c;时光倒流的魔法 在软件开发中&#xff0c;我们经常会遇到需要保存对象状态&#xff0c;并在未来某个时刻恢复的场景。例如&#xff1a; 撤销操作&#xff1a; 文本编辑器中的撤销功能&#xff0c;游戏中的回退操作。事务回滚&am…...

数据库高安全—角色权限:权限管理权限检查

目录 3.3 权限管理 3.4 权限检查 书接上文数据库高安全—角色权限&#xff1a;角色创建角色管理&#xff0c;从角色创建和角色管理两方面对高斯数据库的角色权限进行了介绍&#xff0c;本篇将从权限管理和权限检查方面继续解读高斯数据库的角色权限。 3.3 权限管理 &#x…...

FastAPI 的依赖注入与生命周期管理深度解析

FastAPI 的依赖注入与生命周期管理深度解析 目录 &#x1f527; 依赖注入与 FastAPI 高级特性 1.1 依赖注入的基础与核心概念1.2 FastAPI 的依赖注入机制与设计理念1.3 FastAPI 依赖注入的异步特性 &#x1f579; 生命周期与依赖的异步管理 2.1 依赖的生命周期管理&#xff1…...

【express-generator】05-路由中间件和错误处理(第一阶段收尾)

一、前言 上篇文章我们介绍了express-generator的请求体解析&#xff0c;重点讲了常用的请求体数据格式&#xff08;JSON/URL 编码的表单数据&#xff09;以及一个FILE文件上传&#xff0c;同时搭配代码示范进行辅助理解。 二、本篇重点 我们继续第一阶段的知识&#xff0c;…...

Linux环境下确认并操作 Git 仓库

在软件开发和版本控制中&#xff0c;Git 已成为不可或缺的工具。有时&#xff0c;我们需要确认某个目录是否是一个 Git 仓库&#xff0c;并在该目录中运行脚本。本文将详细介绍如何确认 /usr/local/src/zcxt/backend/policy-system-backend 目录是否是一个 Git 仓库&#xff0c…...

UDP -- 简易聊天室

目录 gitee&#xff08;内有详细代码&#xff09; 图解 MessageRoute.hpp UdpClient.hpp UdpServer.hpp Main.hpp 运行结果&#xff08;本地通信&#xff09; 如何分开对话显示&#xff1f; gitee&#xff08;内有详细代码&#xff09; chat_room zihuixie/Linux_Lear…...

NVIDIA在CES 2025上的三大亮点:AI芯片、机器人与自动驾驶、全新游戏显卡

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

【通俗理解】AI的两次寒冬:从感知机困局到深度学习前夜

AI的两次寒冬&#xff1a;从感知机困局到深度学习前夜 引用&#xff08;中英双语&#xff09; 中文&#xff1a; “第一次AI寒冬&#xff0c;是因为感知机局限性被揭示&#xff0c;让人们失去了对算法可行性的信心。” “第二次AI寒冬&#xff0c;则是因为专家系统的局限性和硬…...

transformer深度学习实战CCTSDB中国交通标志识别

本文采用RT-DETR作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。RT-DETR以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对CCTSDB交通标志数据集进行训练和优化&#xff0c;该数据集包含丰富的CCTSDB交…...

JavaWeb开发(六)XML介绍

1. XML介绍 1.1. 什么是XML &#xff08;1&#xff09;XML 指可扩展标记语言(EXtensible Markup Language)XML 是一种很像HTML的标记语言。   &#xff08;2&#xff09;XML 的设计宗旨是传输数据(目前主要是作为配置文件)&#xff0c;而不是显示数据。   &#xff08;3&a…...

使用pbootcms开发一个企业官网

V:llike620 pbootcms开源PHP建站系统 https://www.pbootcms.com/ 配置网站 域名解析后&#xff0c;网站绑定到程序根目录即可 例如&#xff1a;本地域名是dobot.test &#xff0c;那么也要同步本地的hosts是 127.0.0.1 dobot.test 需要配置下伪静态规则 location / {if (!-e $r…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...