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

C#百万数据处理

C#百万数据处理

在我们经验的不断增长中不可避免的会遇到一些数据量很大操作也复杂的业务
这种情况我们如何取优化如何去处理呢?一般都要根据业务逻辑和背景去进行合理的改进。


文章目录

  • C#百万数据处理
  • 前言
  • 一、项目业务需求和开发背景
    • 项目开发背景
    • 数据量计算
    • 业务需求
    • 业务分析
  • 二、老代码分析
    • 运行逻辑
    • 代码展示
    • 伪代码展示
    • 分析性能低原因
  • 三、优化后的代码分析
    • 运行逻辑
    • 代码展示
    • 伪代码展示
    • 优化了那些问题
  • 总结


前言

这里我给大家带来一个我自己所经历的百万数据处理案例,该案例中会拿优化前和优化后的代码进行对比,让大家更直观的感受优化给项目带来的效率提升。该项目优化用到了:线程同步,多线程,sqlSugar,异步,委托等知识。


一、项目业务需求和开发背景

在这里插入图片描述

项目开发背景

随着连锁门店数量的不断增加,门店商品的库存数据和商品信息的维护业务压力不断增加。数据量越来越大。

数据量计算

假如数据如下:

  • 门店数量:160家
  • 门店商品数量:6000+
  • 还需要更新商品对码信息:6000+
  • 数据接口最多每页查询1000条
  • 那么按以上数据要处理的数据最少就为:966000条

业务需求

  1. 新的商品要做插入操作
  2. 旧的商品要做更新操作(更新库存信息和商品编码厂家等信息)
  3. 门店库存数据变更要在半小时内完成

业务分析

按以上条件我们可以分析出:需要有Insert和Update操作。其中经验丰富的程序员就会发现,其实像这种业务一般 Insert操作最多只占所有业务的20%,Update操作占80%。
注意:
很多小白程序员都是不进行业务分析就直接撸代码,这种方式是不可取的,等你撸完代码之后你就会发现效率根本就不行。后面又花大量时间去优化,还如不体现分析了再进行开发。

二、老代码分析

运行逻辑

老代码的操作流程如下

  1. 查询出所有门店
  2. 循环门店,将门店数据传入操作函数中
  3. 操作函数中再根据传入的门店信息循环去调用接口
  4. 当传入的这个门店的数据拉取完成之后再去操作数据库

代码展示

代码如下:

//查询所有门店商品信息List<StoreCheckCodeDO> storeInfos = b_Stores.GetStoreCheckCodes();//这里是用于更新对码的信息List<ProductInfoDO> infoDOs = new List<ProductInfoDO>();foreach (var storeInfo in storeInfos ){//GetProductInfo的作用是调用总部接口获取并更新商品数据InventoryHelper.GetProductInfo(storeInfo , ref infoDOs );}if(infoDOs.count>0){//更新对码信息InventoryHelper.ChangeProductCheckCode(infoDOs);}

GetProductInfo 的具体实现:

public static bool GetProductInfo(string orgid, ref List<ProductInfoDO> infoDOs, string goodsNo = "", string goodsName = ""){bool rel = false;int pageSize = 1000;int pageNum = 1;List<DslStoreStockDO> list =根据门店ID查询它的商品库存信息Console.WriteLine("开始更新门店:{0}", orgid);//定义个集合来存储拉取到的数据List<StoreStockDO> Stores = new List<StoreStockDO>();while (true){try{DslERPRes<QueryStockRes> res3 =调用总部数据接口每页查询1000条,返回的数据if (res3 != null && res3.code == 0){if (res3.data != null && res3.data.list != null){if (res3.data.total > 0){#region 模型转换//循环总部返回的数据集合,并转成我们需要的DO是实体foreach (var product in res3.data.list){DslStoreStockDO dsl = new DslStoreStockDO();把总部数据转为我们需要的实体存储我们的集合中dslStores.Add(dsl);ProductInfoDO infoDO = 根据总部商品ID查询本地对码表返回商品对码信息实体if (infoDO == null){//如果没有则new一个对象infoDO = new ProductInfoDO();infoDO.LocalSku = product.goodsNo.ToString();}//如果有这个商品就对其数据更新,没有就用新的对象存储后续做新增操作infoDO.Name = product.goodsName;infoDO.DslSku = product.goodsNo.ToString();infoDO.goodsType = product.goodsType;infoDO.proarea = product.prodArea;infoDO.barcode = product.barcode;infoDO.CreateTime = DateTime.Now;infoDO.UpdateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");infoDO.Operator = "系统自动更新";infoDO.IsDelete = false;//查询集合中已存在的该商品ProductInfoDO b_there = infoDOs.Where(t => t.DslSku == product.goodsNo.ToString()).FirstOrDefault();if (b_there != null){//如果有则更新为现在从总部拉取到的商品信息if (infoDO.goodsType != b_there.goodsType){b_there.goodsType = infoDO.goodsType;}if (infoDO.proarea != b_there.proarea){b_there.proarea = infoDO.proarea;}if (infoDO.barcode != b_there.barcode){b_there.barcode = infoDO.barcode;}}else{//插入实体集合中infoDOs.Add(infoDO);}}#endregion//判断该门店商品信息是否拉完if (res3.data.pages == pageNum){//利用list的 Except 方法进行数据筛选var different = list.Except(dslStores, new StoreStockDOComparer()).ToList();//找到没拉到库存的different.ForEach(goodsInfo =>{//把没有从总部拉到商品的库存数据变更为0goodsInfo.goodsQty = 0;goodsInfo.warehouseGoodsQty = 0;});//清除容器内数据从新插入信息变更数据//list 这个list就是我们开头根据门店id查询该门店所有商品库存信息的数据,//所以要清空重新写入我们调整好的数据list = new List<DslStoreStockDO>();list.AddRange(dslStores);list.AddRange(different);//获取完毕,正常结束Console.WriteLine("请稍等正在提交事务...");//_BulkCopyModel方法是做insertOrUpadate操作的。//根据后面传入的主键【goodsNo,placePointNo 】去操作数据库的数据int count = _sqlsugar_DSL._BulkCopyModel(list, "门店库存表", t => new { t.goodsNo, t.placePointNo });rel = count > 0;Console.WriteLine("门店:{0}数据更新成功,操作数据条数:{1}", orgid, count);break;}pageNum++;}else{Console.WriteLine("未查询到更新数据");break;}}else{///获取完毕,正常结束Console.WriteLine("门店:{0}第{1}页数据拉取失败", orgid, pageNum.ToString());break;}}else{//获取异常,强制结束Console.WriteLine("门店:{0}第{1}页数据发起请求失败:{2}", orgid, pageNum.ToString(), res3.msg);break;}}catch (Exception ex){Console.WriteLine("门店:{0}第{1}页数据处理失败:{2}", orgid, pageNum.ToString(), ex.Message);break;}}return rel;}

伪代码展示

上述代码还是比较复杂很长,不太能直观的一眼看到问题所在下面我就写一段伪造代码来给大家展示一下逻辑

代码如下(示例):

门店集合=查询到所有门店商品对码信息收集集合 =new List<T>();foreach (var 单个门店实体 in 门店集合 ){//GetProductInfo的作用是调用总部接口获取并更新商品数据InventoryHelper.GetProductInfo(门店ID, ref 商品对码信息收集集合 );}GetProductInfo(门店ID,ref 门店对码信息收集集合){List<库存数据实体> 旧库存数据=根据门店ID获取库存信息(门店ID);List<库存数据实体> 新库存数据=new  List<库存数据实体>();while(true){页码=1;每页查询数量=1000;总部数据返回数据集合=请求总部数据接口(页码,每页查询数量)foreach (var 数据返回数据实体 in 总部数据返回数据集合 ){数据返回数据实体 转为 库存数据实体 新库存数据.add(库存数据实体)数据返回数据实体数据 取出所需数据组成 商品对码实体门店对码信息收集集合.add(商品对码实体)}if(页码=总部返回数据集合.总页数){新库存数据 做Insert OR Update 操作break;}页码++;}}

分析性能低原因

  • 单线程,需要一个门店一个门店的处理
  • 每处理一个门店都需要去操作一次数据库,做Insert OR Update 操作
  • 单线程请求总部接口线程要等待接口返回才继续往下处理没有达到效率最大化
  • 每次都要去查询门店的所有商品库存,导致不必要的查询开销。

三、优化后的代码分析

运行逻辑

  • 查询出所有门店,根据传入线程数做分组
  • 多线程异步获取总部接口库存数据
  • 当分组的总部数据获取完成后以组为单位更新数据库数据

代码展示

代码如下:

 public static void GetProductInfo(List<DslStoreCheckCodeDO> orgids, int ThreadNumber = 1){if (ThreadNumber > orgids.Count){ThreadNumber = 1;}string startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");List<List<DslStoreCheckCodeDO>> groupedLists = orgids.Select((value, index) => new { Index = index, Value = value }).GroupBy(x => x.Index / (orgids.Count() / ThreadNumber)).Select(x => x.Select(v => v.Value).ToList()).ToList();List<ProductInfoDO> outval = new List<ProductInfoDO>();int _ThreadCount = groupedLists.Count();int finishcount = 0;object locker = new object();foreach (var dslStores in groupedLists){new Thread(async () =>{string TID = Thread.CurrentThread.ManagedThreadId.ToString("00");int count = 0;List<ProductInfoDO> productInfos = new List<ProductInfoDO>();List<DslStoreStockDO> dslStock = new List<DslStoreStockDO>();foreach (var StoreInfo in dslStores){count++;Console.WriteLine("线程ID[{0}]剩余【{1}/{2}】", TID, dslStores.Count, count);string orgid = StoreInfo.DslStoreNo;List<ProductS> products = await GetProductInfo(orgid);#region 模型转换foreach (var product in products){DslStoreStockDO dsl = new DslStoreStockDO();dsl.placePointNo = orgid;dsl.goodsNo = product.goodsNo;dsl.goodsId = product.goodsId;dsl.goodsName = product.goodsName;dsl.goodsType = string.IsNullOrWhiteSpace(product.goodsType) ? "无" : product.goodsType;dsl.prodArea = product.prodArea ?? "无";dsl.barcode = string.IsNullOrWhiteSpace(product.barcode) ? "无" : product.barcode;dsl.goodsQty = product.goodsQty;dsl.warehouseGoodsQty = product.warehouseGoodsQty ?? 0;dsl.purPrice = product.purPrice ?? 0;dsl.retailPrice = product.retailPrice;dsl.salesTaxRate = product.salesTaxRate;dsl.cretime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");dsl.isChange = true;dslStock.Add(dsl);ProductInfoDO infoDO = dSL_ERP.GetCodeCahe(product.goodsNo.ToString());if (infoDO == null){infoDO = new ProductInfoDO();infoDO.LocalSku = product.goodsNo.ToString();}infoDO.Name = product.goodsName;infoDO.DslSku = product.goodsNo.ToString();infoDO.goodsType = product.goodsType;infoDO.proarea = product.prodArea;infoDO.barcode = product.barcode;infoDO.CreateTime = DateTime.Now;infoDO.UpdateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");infoDO.Operator = "系统自动更新";infoDO.IsDelete = false;productInfos.Add(infoDO);}#endregion}if (count == dslStores.Count){   //分配的门店处理完成后再同一操作数据库List<string> SotoreIds = dslStores.Select(t => t.DslStoreNo).ToList();List<DslStoreStockDO> Oldstocks = _sqlsugar_DSL.GetModelList<DslStoreStockDO>("StoreStock", t => SotoreIds.Contains(t.placePointNo)); List<DslStoreStockDO> newStocks = dslStock.Except(Oldstocks, new StoreStockDOComparer()).ToList();List<DslStoreStockDO> commonStocks = dslStock.Except(newStocks, new StoreStockDOComparer()).ToList();try{if (Oldstocks.Count > 0){var diffent = Oldstocks.Except(dslStock, new StoreStockDOComparer()).ToList();diffent.ForEach(goodsInfo =>{goodsInfo.goodsQty = 0;goodsInfo.warehouseGoodsQty = 0;});commonStocks.AddRange(diffent);}Console.WriteLine("请稍等正在提交...");int InsNumber = 0;if (newStocks.Count > 0){InsNumber = await _sqlsugar_DSL.AsynBulkCopyModel(newStocks, "StoreStock", t => new { t.goodsNo, t.placePointNo });}int UpdNumber = await _sqlsugar_DSL.AsynBulkUpdateModel(commonStocks, "StoreStock", new string[] { "goodsNo", "placePointNo" }, new string[] { "placePointNo", "goodsNo", "goodsId", "goodsName", "goodsType", "prodArea", "barcode", "goodsQty", "warehouseGoodsQty", "purPrice", "retailPrice", "salesTaxRate", "cretime", "isChange" });Console.WriteLine("提交成功,更新{0}条数据,插入{1}条数据", UpdNumber, InsNumber);}catch (Exception ex){Console.WriteLine("线程{0}内部报错:{1}", TID, ex.Message);}}lock (locker){outval.AddRange(productInfos);finishcount++;Monitor.Pulse(locker); //完成,通知等待队列,告知已完,执行下一个。}}).Start();}lock (locker){while (finishcount != _ThreadCount){Monitor.Wait(locker);//等待}}IEnumerable<ProductInfoDO> infoDOs = outval.OrderByDescending(x => x.UpdateTime).GroupBy(x => new { x.DslSku, x.barcode }).Select(y => y.First());Console.WriteLine("开始更新商品对码表,待更新数:{0}", infoDOs.Count());if (infoDOs.Count() > 0){Console.WriteLine("正在提交...");ChangeProductCheckCode(infoDOs.ToList());Dictionary<string, string> pairs = new Dictionary<string, string>();pairs.Add("JsonStr", CommonFun.Base64Encode(JsonConvert.SerializeObject(infoDOs)));string rel = HttpHelper.HttpPost("...", pairs);Console.WriteLine("商品对码表跟新成功,商品信息表更新:{0}", rel);}Console.WriteLine("【全量更新所有门店】执行完毕线程挂起24小时...[Start:{0}|End:{1}]", startTime, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));#region 异步获取商品信息async Task<List<ProductS>> GetProductInfo(string orgid){List<ProductS> products = new List<ProductS>();string res = await Task.Run(() =>{int pageNum = 1;int pageSize = 1000;while (true){QueryStockReq req3 = new QueryStockReq();req3.goodsno = "";req3.goodsName = "";req3.pageNum = pageNum;req3.pageSize = pageSize;req3.placePointNo = orgid;Console.WriteLine("门店【{1}】开始获取第{0}页数据-线程ID【{2}】", req3.pageNum.ToString(), orgid, Thread.CurrentThread.ManagedThreadId.ToString("00"));DslERPReq dslERP23 = new DslERPReq(req3);DslERPRes<QueryStockRes> res3 = dSL_ERP.queryStock(dslERP23);if (res3 != null && res3.code == 0){if (res3.data != null && res3.data.list != null){if (res3.data.total > 0){products.AddRange(res3.data.list);if (res3.data.pages == pageNum){break;}pageNum++;}else{Console.WriteLine("未查询到更新数据,返回数据{0},数据JSON:【{1}】", res3.msg, JsonConvert.SerializeObject(res3));break;}}else{Console.WriteLine("门店:{0}第{1}页数据拉取失败返回信息{2}", orgid, req3.pageNum.ToString(), res3.msg);break;}}else{Console.WriteLine("门店:{0}第{1}页数据发起请求失败:{2}", orgid, req3.pageNum.ToString(), res3.msg);}}return "";});return products;}#endregion}

伪代码展示

 public static void GetProductInfo(List<门店信息实体> 门店信息实体集合, int 处理线程数量= 1){if (处理线程数量 > 门店信息实体集合.Count){处理线程数量 = 1;}string startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");List<List<门店信息实体>> 门店分组集合= 门店信息实体集合.Select((value, index) => new { Index = index, Value = value }).GroupBy(x => x.Index / (门店信息实体集合.Count() / 处理线程数量)).Select(x => x.Select(v => v.Value).ToList()).ToList();List<商品对码实体> outval = new List<商品对码实体>();int _ThreadCount = 门店分组集合.Count();int finishcount = 0;object locker = new object();//线程锁foreach (var 门店实体集合 in 门店分组集合){new Thread(async () =>{string TID = Thread.CurrentThread.ManagedThreadId.ToString("00");int count = 0;List<ProductInfoDO> productInfos = new List<ProductInfoDO>();List<库存数据实体> 总部库存数据集合= new List<库存数据实体>();foreach (var StoreInfo in 门店实体集合){count++;Console.WriteLine("线程ID[{0}]剩余【{1}/{2}】", TID, 门店实体集合.Count, count);string orgid = StoreInfo.门店ID;//这里是异步从总部库存信息接口获取商品库存信息List<ProductS> products = await GetProductInfo(orgid);#region 模型转换foreach (var product in products){库存数据实体dsl = new 库存数据实体();dsl.placePointNo = orgid;dsl.goodsNo = product.goodsNo;dsl.goodsId = product.goodsId;dsl.goodsName = product.goodsName;dsl.goodsType = string.IsNullOrWhiteSpace(product.goodsType) ? "无" : product.goodsType;dsl.prodArea = product.prodArea ?? "无";dsl.barcode = string.IsNullOrWhiteSpace(product.barcode) ? "无" : product.barcode;dsl.goodsQty = product.goodsQty;dsl.warehouseGoodsQty = product.warehouseGoodsQty ?? 0;dsl.purPrice = product.purPrice ?? 0;dsl.retailPrice = product.retailPrice;dsl.salesTaxRate = product.salesTaxRate;dsl.cretime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");dsl.isChange = true;总部库存数据集合.Add(dsl);ProductInfoDO infoDO = dSL_ERP.GetCodeCahe(product.goodsNo.ToString());if (infoDO == null){infoDO = new ProductInfoDO();infoDO.LocalSku = product.goodsNo.ToString();}infoDO.Name = product.goodsName;infoDO.DslSku = product.goodsNo.ToString();infoDO.goodsType = product.goodsType;infoDO.proarea = product.prodArea;infoDO.barcode = product.barcode;infoDO.CreateTime = DateTime.Now;infoDO.UpdateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");infoDO.Operator = "系统自动更新";infoDO.IsDelete = false;productInfos.Add(infoDO);}#endregion}//注意这里我为什么要用count来判断这组是否执行完成,因为我们操作数据库的语句优化为了异步的//而Look语句内是不支持await 语句的,所有利用组合里的门店数和已处理数来判断if (count == 门店实体集合.Count){   //分配的门店处理完成后再同一操作数据库List<string> SotoreIds = 门店实体集合.Select(t => t.门店ID).ToList();// 查询出这个批次里所有门店的老的库存数据List<库存数据实体> Oldstocks = _sqlsugar_DSL.GetModelList<库存数据实体>("StoreStock", t => SotoreIds.Contains(t.门店ID)); //List<库存数据实体> newStocks = 总部库存数据集合.Except(Oldstocks, new StoreStockDOComparer()).ToList();List<库存数据实体> commonStocks = 总部库存数据集合.Except(newStocks, new StoreStockDOComparer()).ToList();try{if (Oldstocks.Count > 0){var diffent = Oldstocks.Except(总部库存数据集合, new StoreStockDOComparer()).ToList();diffent.ForEach(goodsInfo =>{goodsInfo.goodsQty = 0;goodsInfo.warehouseGoodsQty = 0;});commonStocks.AddRange(diffent);}Console.WriteLine("请稍等正在提交...");int InsNumber = 0;if (newStocks.Count > 0){InsNumber = await _sqlsugar_DSL.AsynBulkCopyModel(newStocks, "StoreStock", t => new { t.goodsNo, t.placePointNo });}int UpdNumber = await _sqlsugar_DSL.AsynBulkUpdateModel(commonStocks, "StoreStock", new string[] { "goodsNo", "placePointNo" }, new string[] { "placePointNo", "goodsNo", "goodsId", "goodsName", "goodsType", "prodArea", "barcode", "goodsQty", "warehouseGoodsQty", "purPrice", "retailPrice", "salesTaxRate", "cretime", "isChange" });Console.WriteLine("提交成功,更新{0}条数据,插入{1}条数据", UpdNumber, InsNumber);}catch (Exception ex){Console.WriteLine("线程{0}内部报错:{1}", TID, ex.Message);}}lock (locker){outval.AddRange(productInfos);finishcount++;Monitor.Pulse(locker); //完成,通知等待队列,告知已完,执行下一个。}}).Start();}lock (locker){while (finishcount != _ThreadCount){Monitor.Wait(locker);//等待}}IEnumerable<ProductInfoDO> infoDOs = outval.OrderByDescending(x => x.UpdateTime).GroupBy(x => new { x.DslSku, x.barcode }).Select(y => y.First());Console.WriteLine("开始更新商品对码表,待更新数:{0}", infoDOs.Count());if (infoDOs.Count() > 0){Console.WriteLine("正在提交...");ChangeProductCheckCode(infoDOs.ToList());Dictionary<string, string> pairs = new Dictionary<string, string>();pairs.Add("JsonStr", CommonFun.Base64Encode(JsonConvert.SerializeObject(infoDOs)));string rel = HttpHelper.HttpPost("...", pairs);Console.WriteLine("商品对码表跟新成功,商品信息表更新:{0}", rel);}Console.WriteLine("【全量更新所有门店】执行完毕线程挂起24小时...[Start:{0}|End:{1}]", startTime, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));#region 异步获取商品信息async Task<List<ProductS>> GetProductInfo(string orgid){List<ProductS> products = new List<ProductS>();string res = await Task.Run(() =>{int pageNum = 1;int pageSize = 1000;while (true){QueryStockReq req3 = new QueryStockReq();req3.goodsno = "";req3.goodsName = "";req3.pageNum = pageNum;req3.pageSize = pageSize;req3.placePointNo = orgid;Console.WriteLine("门店【{1}】开始获取第{0}页数据-线程ID【{2}】", req3.pageNum.ToString(), orgid, Thread.CurrentThread.ManagedThreadId.ToString("00"));DslERPReq dslERP23 = new DslERPReq(req3);DslERPRes<QueryStockRes> res3 = dSL_ERP.queryStock(dslERP23);if (res3 != null && res3.code == 0){if (res3.data != null && res3.data.list != null){if (res3.data.total > 0){products.AddRange(res3.data.list);if (res3.data.pages == pageNum){break;}pageNum++;}else{Console.WriteLine("未查询到更新数据,返回数据{0},数据JSON:【{1}】", res3.msg, JsonConvert.SerializeObject(res3));break;}}else{Console.WriteLine("门店:{0}第{1}页数据拉取失败返回信息{2}", orgid, req3.pageNum.ToString(), res3.msg);break;}}else{Console.WriteLine("门店:{0}第{1}页数据发起请求失败:{2}", orgid, req3.pageNum.ToString(), res3.msg);}}return "";});return products;}#endregion}

优化了那些问题

  • 从总部取数据变为了异步多线程避免了线程阻塞
  • 门店按组合处理减小了数据库操作次数
  • 操作数据库改为异步避免阻塞

总结

以上就是我个人所经历的大数据处理,虽然优化的并不算完美但是还是总结出了不少经验,也从中学习到了很多,比如,单线程和多线程的运用以及委托和线程同步等知识。

相关文章:

C#百万数据处理

C#百万数据处理 在我们经验的不断增长中不可避免的会遇到一些数据量很大操作也复杂的业务 这种情况我们如何取优化如何去处理呢&#xff1f;一般都要根据业务逻辑和背景去进行合理的改进。 文章目录 C#百万数据处理前言一、项目业务需求和开发背景项目开发背景数据量计算业务需…...

windows端口占用

1.查看当前端口被哪个进程占用了&#xff08;进入到CMD中&#xff09; netstat -ano|findstr "8990"输出结果为&#xff1a; TCP 127.0.0.1:8990 0.0.0.0:0 LISTENING 2700 我们发现8990端口被2700进程占用了 2.基于进程号找进程名称 tasklist|findstr "2700&qu…...

如何理解Diffusion

Diffusion算法可以有多个角度进行理解&#xff0c;不同的理解方式只是对目标函数进行了不同的解释。其主体思想是不变的&#xff0c;可以归纳为&#xff1a; 训练时通过图片逐步添加噪声&#xff0c;变为一个纯噪声。然后学习每一步的噪声。推理时给定一个随机噪声图片&#x…...

自然语言处理从入门到应用——LangChain:模型(Models)-[聊天模型(Chat Models):使用少量示例和响应流式传输]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 使用少量示例 本部分的内容介绍了如何在聊天模型&#xff08;Chat Models&#xff09;中使用少量示例。关于如何最好地进行少量示例提示尚未形成明确的共识。因此&#xff0c;我们尚未固定任何关于此的抽象概念&#…...

Java在线OJ项目(三)、前后端交互API模块

Java在线OJ项目&#xff08;三&#xff09;、前后端交互API模块 1. 客户端向服务器请求所有题目 或者 单个题目前端获取所有题目获取一个题目 后端 2. 后端读取前端提交的代码&#xff0c;进行编译运行&#xff0c;返回结果前端提交代码后端处理 1. 客户端向服务器请求所有题目…...

项目——负载均衡在线OJ

目录 项目介绍开发环境所用技术项目宏观结构编写思路1. 编写compile_server1.1 编译模块编写1.2 运行功能1.3compile_runner 编译与运行1.4 编写compile_server.cpp调用compile_run模块&#xff0c;形成网络服务 2. 编写基于MVC的oj_server2.1 oj_server.cpp的编写2.2 oj_model…...

idea连接远程服务器上传war包文件

idea连接远程服务器&上传war包 文章目录 idea连接远程服务器&上传war包1. 连接服务器2.上传war包 1. 连接服务器 选择Tools -> Start SSH Session 添加配置 连接成功 2.上传war包 Tools -> Deployment -> Browse Remote Host 点击右侧标签&#xff0c;点击&…...

使用PyGWalker可视化分析表格型数据

大家好&#xff0c;可以想象一下在Jupyter Notebook中拥有大量数据&#xff0c;想要对其进行分析和可视化。PyGWalker就像一个神奇的工具&#xff0c;能让这项工作变得超级简单。它能获取用户的数据&#xff0c;并将其转化为一种特殊的表格&#xff0c;可以与之交互&#xff0c…...

Visual C++中的虚函数和纯虚函数(以外观设计模式为例)

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来说说Visual C中的虚函数和纯虚函数。该系列帖子全部使用我本人自创的对比学习法。也就是当C学不下去的时候&#xff0c;就用JAVA实现同样的代码&#xff0c;然后再用对比的方法把C学会。 直接说虚函数…...

电子元器件选型与实战应用—01 电阻选型

大家好, 我是记得诚。 这是《电子元器件选型与实战应用》专栏的第一篇文章,今天的主角是电阻,在每一个电子产品中,都少不了电阻的身影,其重要性不言而喻。 文章目录 1. 入门知识1.1 基础1.2 常用品牌1.3 电阻的种类2. 贴片电阻标识2.1 三位数标注法2.2 四位数标注法2.3 小…...

javascript 模板引擎

使用场景 在实际开发中&#xff0c;一般都是使用动态请求数据来更新页面&#xff0c;服务器端通常返回json格式的数据&#xff0c;正常操作是我们手动的去拼装HTML&#xff0c;但麻烦且容易出错&#xff0c;因此出现了一些用模版生成HTML的的框架叫js模板引擎如&#xff1a;jq…...

【数据结构】带头+双向+循环链表(DList)(增、删、查、改)详解

一、带头双向循环链表的定义和结构 1、定义 带头双向循环链表&#xff0c;有一个数据域和两个指针域。一个是前驱指针&#xff0c;指向其前一个节点&#xff1b;一个是后继指针&#xff0c;指向其后一个节点。 // 定义双向链表的节点 typedef struct ListNode {LTDataType dat…...

接口自动化测试平台

下载了大神的EasyTest项目demo修改了下<https://testerhome.com/topics/12648 原地址>。也有看另一位大神的HttpRunnerManager<https://github.com/HttpRunner/HttpRunnerManager 原地址>&#xff0c;由于水平有限&#xff0c;感觉有点复杂~~~ 【整整200集】超超超…...

【物联网】微信小程序接入阿里云物联网平台

微信小程序接入阿里云物联网平台 一 阿里云平台端 1.登录阿里云 阿里云物联网平台 点击进入公共实例&#xff0c;之前没有的点进去申请 2.点击产品&#xff0c;创建产品 3.产品名称自定义&#xff0c;按项目选择类型&#xff0c;节点类型选择之恋设备&#xff0c;联网方式W…...

PKG内容查看工具:Suspicious Package for Mac安装教程

Suspicious Package Mac版是一款Mac平台上的查看 PKG 程序包内信息的应用&#xff0c;Suspicious Package Mac版支持查看全部包内全部文件&#xff0c;比如需要运行的脚本&#xff0c;开发者&#xff0c;来源等等。 suspicious package mac使用简单&#xff0c;只需在选择pkg安…...

第16节:R语言医学分析实例:肺切除手术的Apriori关联规则分析

关联规则 肺切除手术的Apriori关联规则分析。 分析的目的是确定患有肺癌并需要接受肺切除术的患者的共病症状。 了解哪些症状是共病的可以帮助改善患者护理和药物处方。 分析类型是关联规则学习,通过探索变量之间的关联或频繁项集,尝试在大型数据集中找到见解和隐藏关系(H…...

ChatGPT+MidJourney 3分钟生成你的动画故事

chatgpt是真的火了&#xff0c;chatgpt产生了一个划时代的意义——自chatgpt起&#xff0c;AI是真的要落地了。 chatgpt能做的事情太多了&#xff0c;多到最初开发模型的程序员自己&#xff0c;也没法说得清楚chatgpt都能做啥&#xff0c;似乎只要你能想得到&#xff0c;它都有…...

在CSDN学Golang云原生(Kubernetes Pod调度)

一&#xff0c;NodeSelector定向调度 在 Kubernetes 中&#xff0c;可以使用 NodeSelector 字段来指定 Pod 调度到哪些节点上运行。NodeSelector 是一个键值对的 map&#xff0c;其中键是节点的标签名&#xff0c;值是标签值。具体步骤如下&#xff1a; 在节点上添加标签 首…...

Rust vs Go:常用语法对比(七)

题图来自 Go vs Rust: Which will be the top pick in programming?[1] 121. UDP listen and read Listen UDP traffic on port p and read 1024 bytes into buffer b. 听端口p上的UDP流量&#xff0c;并将1024字节读入缓冲区b。 import ( "fmt" "net&qu…...

【HarmonyOS】API6使用storage实现轻量级数据存储

写在前面 本篇内容基于API6 JS语言进行开发&#xff0c;通过结合轻量级数据存储开发指导的文档&#xff0c;帮助大家完成一个实际的代码案例&#xff0c;通过这个小案例&#xff0c;可以实现简单数据的存储。 参考文档&#xff1a;文档中心 1、页面布局 首先我们编写一个简单…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...