C#学习26天:内存优化的几种方法
1.减少对象创建
使用场景:
- 在循环或密集计算中频繁创建对象时。
- 涉及大量短生命周期对象的场景,比如日志记录或字符串拼接。
- 游戏开发中,需要频繁更新对象状态时。
说明:
- 重用对象可以降低内存分配和垃圾回收的开销。
- 使用对象池(Object Pooling)技术来管理可重用对象的生命周期
示例:
// 不优化的情况:每次都创建新的 StringBuilder
for (int i = 0; i < 1000; i++)
{var builder = new StringBuilder();builder.Append("Number: ");builder.Append(i);Console.WriteLine(builder.ToString());
}// 优化后的情况:重用同一个 StringBuilder
var sharedBuilder = new StringBuilder();
for (int i = 0; i < 1000; i++)
{sharedBuilder.Clear();sharedBuilder.Append("Number: ");sharedBuilder.Append(i);Console.WriteLine(sharedBuilder.ToString());
}
2.使用合适的数据结构
使用场景:
- 数据量固定且不需要动态增删时,使用数组代替列表。
- 需要快速查找、添加和删除操作时,选择字典(Dictionary)或哈希表(HashSet)。
- 在多线程环境中使用并发集合(如 ConcurrentDictionary)以保证线程安全。
说明:
- 选择合适的数据结构可以提高程序的性能和内存利用率。
- 在使用大型数据集合时,数据结构的选择尤为关键。
示例:
// 使用 List<T>
List<int> numbersList = new List<int> { 1, 2, 3, 4, 5 };// 使用 Array
int[] numbersArray = new int[] { 1, 2, 3, 4, 5 };// 当数据量固定时,Array 比 List<T> 更节省内存Dictionary<int, string> employeeDirectory = new Dictionary<int, string>();employeeDirectory[1002] = "Robert";//快速查找更新,字典更快捷
3.使用 struct 代替 class(在合适的场景)
使用场景:
- 小型数据结构,如几何坐标(Point)、颜色(Color)等。
- 不需要继承或复杂对象行为的简单数据容器。
- 大量创建和销毁对象的场景,如物理引擎中的向量计算。
说明:
- struct 提供值语义,存储在栈上,减少了堆内存的使用。
- 需要注意避免 struct 过大,因为大结构体会增加复制的成本。
示例:
// 使用 class
class PointClass
{public int X { get; set; }public int Y { get; set; }
}
// 使用 struct
struct PointStruct
{public int X { get; set; }public int Y { get; set; }
}// struct 通常会节省内存,尤其是在大量小对象的情况下
// 使用 class
void ProcessPointsClass()
{for (int i = 0; i < 1000000; i++){PointClass p1 = new PointClass(i, i);}
}
// 使用 struct
void ProcessPointsStruct()
{for (int i = 0; i < 1000000; i++){PointStruct p1 = new PointStruct(i, i);}
}
4.避免装箱和拆箱
使用场景:
- 在高性能要求的代码中,尤其是涉及到泛型集合的频繁操作。
- 需要使用非泛型集合或接口时,尽量避免将值类型装箱。
- 数据密集型应用,如数据处理、实时计算等。
说明:
- 使用泛型集合(如 List<int> 而非 ArrayList)可以避免装箱。
- 频繁装箱和拆箱不仅浪费内存,还会影响性能。
示例:
using System;
using System.Collections;
class Program
{static void Main(){ArrayList list = new ArrayList();// 装箱:整数被包装成对象list.Add(42);// 拆箱:对象被转换回整数int value = (int)list[0];Console.WriteLine($"Value: {value}");}
}using System;
using System.Collections.Generic;
class Program
{static void Main(){List<int> list = new List<int>();// 不需要装箱:整数直接存储为值类型list.Add(42);// 不需要拆箱:整数直接检索为值类型int value = list[0];Console.WriteLine($"Value: {value}");}
}
5.使用 StringBuilder 替代字符串连接
使用场景:
- 在循环中进行字符串拼接操作。
- 构造长文本或动态生成 HTML/CSS/SQL 查询等。
- 需要频繁修改字符串的场景,如日志记录系统。
说明:
- StringBuilder 是为高效字符串操作而设计的,避免了不必要的中间对象。
- 尤其适用于构建长字符串或需要多次修改字符串的场景
示例:
// 不使用 StringBuilder
string result = "";
for (int i = 0; i < 100; i++)
{result += i.ToString(); // 创建多个中间字符串对象
}// 使用 StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++)
{sb.Append(i.ToString());
}
string optimizedResult = sb.ToString(); // 更高效
6.使用 using 语句管理资源
使用场景:
- 需要使用 IDisposable 接口的对象,如文件流、数据库连接、网络资源等。
- 网络通信、文件读写、数据库操作等需要保证资源正确释放的场景。
- 任何需要显式释放资源以避免内存泄漏的情况。
说明:
- using 语句确保对象在使用完后立即释放资源,减少内存压力。
- 限定资源的生存周期,避免资源长时间占用。
示例:
using System;
using System.IO;class Program
{static void Main(){string filePath = "example.txt";// 使用 using 语句确保文件在读取后正确关闭using (StreamReader reader = new StreamReader(filePath)){string line;while ((line = reader.ReadLine()) != null){Console.WriteLine(line);}} // 离开 using 块时,reader 对象的 Dispose 方法被自动调用Console.WriteLine("文件读取完毕,资源已释放。");}
}
7.合理使用弱引用 WeakReference
使用场景:
- 需要缓存数据但又不希望缓存对象长期占用内存时。
- 实现某种形式的对象缓存,如图像缓存、数据库查询结果缓存等。
- 需要在内存不足时允许垃圾回收的非关键对象。
说明:
- 弱引用允许垃圾回收器回收未使用的对象,避免内存溢出。
- 适合偶尔使用但不希望长期占用内存的对象。
示例:
using System;
using System.Collections.Generic;
using System.Drawing;class Program
{// 使用字典来存储图像的弱引用缓存static Dictionary<string, WeakReference> imageCache = new Dictionary<string, WeakReference>();static void Main(){string imagePath = "example.png";Bitmap image = LoadImage(imagePath);if (image != null){Console.WriteLine("图像已加载并缓存。");}else{Console.WriteLine("图像加载失败。");}// 强制垃圾回收以演示弱引用效果GC.Collect();GC.WaitForPendingFinalizers();// 再次尝试从缓存加载图像image = LoadImage(imagePath);if (image != null){Console.WriteLine("图像已从缓存中重新加载。");}else{Console.WriteLine("图像已被垃圾回收器回收。");}}static Bitmap LoadImage(string path){if (imageCache.TryGetValue(path, out WeakReference weakRef) && weakRef.IsAlive){Console.WriteLine("从缓存中获取图像...");return weakRef.Target as Bitmap;}else{Console.WriteLine("加载新图像...");Bitmap img = new Bitmap(path);// 将图像加载到缓存中imageCache[path] = new WeakReference(img);return img;}}
}
这些优化策略在合适的场景中可以显著提高内存使用效率,并提高应用程序的整体性能。根据具体的应用需求,选择适当的方法进行优化是关键。希望这些场景描述能帮助你更好地理解和应用这些内存优化策略!如果需要进一步的帮助,请随时提问。
相关文章:
C#学习26天:内存优化的几种方法
1.减少对象创建 使用场景: 在循环或密集计算中频繁创建对象时。涉及大量短生命周期对象的场景,比如日志记录或字符串拼接。游戏开发中,需要频繁更新对象状态时。 说明: 重用对象可以降低内存分配和垃圾回收的开销。使用对象池…...
功能测试向量是个什么概念
在半导体测试领域,功能测试向量(Functional Test Vector) 是一个非常重要的概念。以下是对其的详细解释: 1. 什么是功能测试向量? 功能测试向量是一组输入信号和预期输出信号的集合,用于验证芯片的功能是否…...

C++之string的模拟实现
string 手写C字符串类类的基本结构与成员变量一、构造函数与析构函数二、赋值运算符重载三、迭代器支持四、内存管理与扩容机制五、字符串操作函数六、运算符重载总结 手写C字符串类 从零实现一个简易版std::string 类的基本结构与成员变量 namespace zzh { class string { …...

Python打卡第38天
浙大疏锦行 作业: 了解下cifar数据集,尝试获取其中一张图片 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader , Dataset # DataLoader 是 PyTorch 中用于加载数据的工具 from torchvision im…...
【网络安全】轻量敏感路径扫描工具
订阅专栏,获取文末项目源码。 文章目录 工具简介工具特点项目结构使用方法1.环境准备2.配置目标URL3.运行扫描4.结果查看5.自定义扩展项目源码工具简介 该工具是一款基于Python的异步敏感路径扫描工具,用于检测目标网站是否存在敏感文件或路径泄露(如配置文件、密钥、版本控…...
K8S查看pod资源占用和物理机器IP对应关系
方法1:使用管道组合多个grep kubectl describe node | grep -E "Resource|InternalIP" -A 3方法2:显示节点名称和IP地址的对应关系 kubectl describe node | grep -E "Name:|InternalIP:"方法3:更清晰的格式化输出 ku…...
Java Spring 之拦截器HandlerInterceptor详解与实战
目录 一、拦截器的作用1.1 请求处理前的拦截1.2 请求处理后的拦截1.3 请求完成后的拦截 二、创建拦截器2.1 实现 HandlerInterceptor 接口2.2 注册拦截器 三、拦截器的使用场景3.1 权限校验3.2 日志记录3.3 性能监控 四、总结 在 Spring 框架中,拦截器( …...

开源第三方库发展现状
摘要:当前,开源第三方库生态正呈现爆发式增长趋势。GitHub 目前已托管超过 4.2 亿个代码仓库,远超早期统计的 1 亿规模,显示出开发者社区的活跃度持续攀升。同时,37 个主流包管理器所维护的开源组件数量可能已达到数千…...

JavaSE核心知识点04工具04-02(IDEA)
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 JavaSE核心知识点04工具04-02(ID…...

NodeMediaEdge通道管理
NodeMediaEdge任务管理 简介 NodeMediaEdge是一款部署在监控摄像机网络前端中,拉取Onvif或者rtsp/rtmp/http视频流并使用rtmp/kmp推送到公网流媒体服务器的工具。 在未使用NodeMediaServer的情况下,或者对部分视频流需要单独推送的需求,也可…...
25、web场景-【源码分析】-静态资源原理
25、web场景-【源码分析】-静态资源原理 静态资源原理主要涉及Spring Boot如何管理和提供静态文件,如CSS、JavaScript、图片等。以下是详细的分析: #### 默认静态资源目录 Spring Boot默认将以下目录作为静态资源的存放位置: - classpath:/…...
qt结构化绑定的重大缺陷:只能创建局部变量
根据你的描述,问题出现在使用 std::make_tuple 和结构化绑定(structured binding)初始化多个成员变量时。这种初始化方式在C++中是合法的,但可能会导致一些问题,尤其是在类的成员变量初始化中。 问题分析 成员变量初始化顺序: 在C++中,类的成员变量的初始化顺序是按照它…...

历年中南大学计算机保研上机真题
2025中南大学计算机保研上机真题 2024中南大学计算机保研上机真题 2023中南大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 进制转换 题目描述 请写出一段程序,将十进制数字转为八进制。 输入格式 第一行输入 T T T ( 1 ≤ T ≤…...
端口映射不通的原因有哪些?路由器设置后公网访问本地内网失败分析
本地网络地址通过端口映射出去到公网使用,是较为常用的一种传统方案。然而,很多环境下和很多普通人员在实际使用中,却往往会遇到端口映射不通的问题。端口映射不通的主要原因包括公网IP缺失(更换nat123类似映射工具方案࿰…...
Vue3 封装el-table组件
封装一个el-table组件:子组件仅负责事件触发,业务逻辑(如API调用、状态更新)由父组件实现 <template><el-table:data"tableData"borderstripestyle"width: 100%; height: calc(100% - 32px);"class…...
Python爬虫实战:研究Requests-HTML库相关技术
1. 引言 1.1 研究背景与意义 随着互联网数据量的爆炸式增长,网络爬虫已成为数据获取的重要工具,广泛应用于市场调研、舆情分析、学术研究等领域。传统爬虫技术在面对现代 JavaScript 动态渲染网页时面临挑战,而 Requests-HTML 库通过集成浏览器渲染引擎,为解决这一问题提…...

Azure Devops pipeline 技巧和最佳实践
1. 如何显示release pipeline ? 解决方法: 登录devops, 找到organization - pipeline - setting下的Disable creation of classic release pipelines,禁用该选项。 然后在project - pipeline - setting,禁用Disable creation of classic release pipelines 现在可以看到r…...
云原生应用架构设计原则与落地实践:从理念到方法论
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、云原生:现代架构的起点与范式变革 1.1 什么是云原生? 云原生(Cloud Native)是一种面…...

一起学数据结构和算法(三)| 字符串(线性结构)
字符串(String) 字符串是由字符组成的有限序列,在计算机中通常以字符数组形式存储,支持拼接、查找、替换等操作。 简介 字符串是计算机科学中最常用的数据类型之一,由一系列字符组成的有限序列。在大多数编程语言中&…...
udp 传输实时性测量
UDP(用户数据报协议)是一种无连接的传输协议,适用于实时性要求较高的应用,如视频流、音频传输和游戏等。测量UDP传输的实时性可以通过多种工具和方法实现,以下是一些常见的方法和工具: 1. 使用 iperf 测试…...

超级对话:大跨界且大综合的学问融智学应用场景述评(不同第三方的回应)之一
您敏锐的洞察力值得赞赏!让我们穿透表层,直抵邹晓辉教授梦境与灵感中潜藏的文明级变革逻辑。以下是基于认知科学、技术哲学与文明演进的三维深度解构: 第一性原理突破:知识存在的本质重构 1. 从“描述性知识”到“体验性认知”的…...

【ArcGIS微课1000例】0147:Geographic Imager6.2下载安装教程
文章目录 一、软件功能二、下载地址三、安装教程Geographic Imager地图工具使Adobe Photoshop空间图像可以快速高效地工作。它增加了导入,编辑,操作和导出地理空间图像的工具,例如航空和卫星图像。Geographic Imager Mac功能非常强大,拥有栅格数据输出、投影信息修改、基于…...
Android 之 kotlin 语言学习笔记二(编码标准)
1、源文件命名 所有源文件都必须编码为 UTF-8。如果源文件只包含一个顶级类,则文件名应为该类的名称(区分大小写)加上 .kt 扩展名。如果源文件包含多个顶级声明,则应选择一个可描述文件内容的名称(采用 PascalCase 大…...

华为OD机试真题——Boss的收入(分销网络提成计算)(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...
微软云如何申请使用
微软云(Azure)新手“开荒”指南:5步搞定账户,直达云端! 还在为云计算的复杂门槛发愁吗?别担心!当全球83%的企业都在加速“上云”,微软智能云Azure凭借其在全球34个区域、200服务的庞…...

历年西北工业大学计算机保研上机真题
2025西北工业大学计算机保研上机真题 2024西北工业大学计算机保研上机真题 2023西北工业大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 计算整数乘积 题目描述 给定 n n n 组数,每组两个整数,输出这两个整数的乘积。 …...

使用pnpm、vite搭建Phaserjs的开发环境
首先,确保你已经安装了 Node.js 和 npm。然后按照以下步骤操作: 一、使用pnpm初始化一个新的 Vite 项目 pnpm create vite 输入名字 选择模板,这里我选择Vanilla,也可以选择其他的比如vue 选择语言 项目新建完成 二、安装相关依赖 进入项…...

intra-mart执行java方法笔记
一、前言 最近在用intra-mart,感觉官方文档不明不白的,很难搜。 想在intra-mart里执行java,找了半天,终于试出来了。 在此总结一下。 想看官网文档,这个是地址: https://document.intra-mart.jp/library…...

在 Vue 2中使用 dhtmlxGantt 7.1.13组件,并解决使用时遇到的问题汇总.“dhtmlx-gantt“: “^7.1.13“,
一、最终实现的结果gif展示 二、开发步骤简介 1、vue中引用甘特图包dhtmlx-gantt // 可根据项目版本载入适配的版本 npm install dhtmlx-gantt7.1.132、vue文件中引入 <script> import { gantt } from dhtmlx-gantt/codebase/dhtmlxgantt.js import dhtmlx-gantt/code…...

【C++高级主题】命令空间(三):未命名的命名空间
目录 一、未命名的命名空间的基本概念 1.1 定义与特点 1.2 基本语法 1.3 访问方式 1.4 未命名的命名空间的作用 二、未命名的命名空间与静态声明的比较 2.1 静态声明的作用 2.2 未命名的命名空间的优势 2.3 示例代码比较 2.4. 未命名的命名空间的作用域和链接属性 三…...