Web Analytics
yangyang

码农兼一个普普通通小青年

All Posts in 2022


布隆过滤器原理及应用

布隆过滤器(Bloom Filter)是 1970 年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数,主要用于判断一个元素是否在一个集合中。与直接存储数据不同,布隆过滤器是通过一系列随机映射函数,将待存储的数据通过映射函数提取特征,然后将这些特征存储到二进制向量对应的二进制位上(类似于前文的Bitmap存储),当查找某个值时,通过随机映射函数,提取特征,然后检查这些特征所在的二进制位上是否都为1,如果都为1,表示该可能存在在集合中,但只要有一个为0,则一定不在集合中。 …

Bloom Filter Hash table collision

位运算及其应用

位运算符作用于整型对象,并把运算对象看作是二进制位的集合。位运算提供了检查和设置二进制位的功能。通常在编写代码中,相比加减乘除,位运算并不常用,但在有些情况下,位运算有用处。本文首先介绍为位运算的基本概念,然后介绍位运算的应用场景,包括使用Bitmap来存储整型数据,并介绍了在此基础上如何对大量不重复的整型数据进行快速排序,对大量整型数进行去重和快速查找,最后介绍了编程语言对Bitmap思想的实现,包括C++里面的bitset,C#里面的BitArray,并介绍了枚举值中使用位运算的一些例子。 …

bitwise or xor bitmap bitset bitarray

当心文件路径中的Unicode控制字符

最近遇到一个特别诡异的问题,文件明明存在,但是在使用File.Exists判断时却显示为false,经过一番996,发现在获取文件绝对路径的时候,从文件的“属性”-"安全"Tab页里面,复制“对象名称”时,必须从“左往右”选中复制,如果从“右往左”选中复制,则会包含一个不可见的Unicode "u202A"字符(unicode十进制8234),从而导致错误。 …

LRO RLO 0x202A 0x202E

C#中的线程同步构造:用户模式构造和内核模式构造

当多个线程同时访问共享数据对象时,就需要线程同步,以保证数据状态不会被破坏。线程同步的通常做法是加“锁”,以保证某一时刻只有拥有这个锁的对象才能够去操作数据。加“锁”能够保证共享数据不会被破坏,但是它增加了代码的复杂性,并且有时候不容易测试和重现。另外“锁”增加了系统开销,会损害系统性能。本文介绍了C#中的基元用户模式构造和基元内核模式构造两类基本类型构造,并详细介绍了在C#中的实现。 …

ManualResetEvent user-mode kernel-mode volatile interlocked OCC WaitHandle AutoResetEvent Semaphore Mutex

C#中实例方法与虚方法的调用性能比较

实例方法、静态方法这类在编译时就能确定调用对象的方法相比抽象方法、虚方法、接口方法这类动态方法在函数调用方面速度要快一些,但这个耗时差别,与本身函数内部逻辑运行的耗时相比,在绝大多数情况下可以忽略不计。所以我们在写代码时,不用纠结使用虚方法、抽象方法或接口方法在方法调用时的开销,反而需要优先考虑的是代码的扩展性、灵活性,更进一步要关注函数方法内部算法逻辑或者流程的优化。 …

virtual method

.NET中的一些无损压缩算法

股票的行情这种时序数据类型,数据冗余度和相似度较高,天然适合进行压缩。本文分析了几种无损压缩算法,分别是C#内置的和SharpZipLib的GZip、Zstd、LZ4以及Snappy。在对比这几种算法的压缩率,压缩时间后发现,Zstd具有比较好的压缩率和压缩速度,基本能满足行情数据处理以及传输效率的要求。 …

GZip SharpZipLib Zstd LZ4 Snappy lossless compression algorithm

C++中的引用和指针

我本人只有一点C基础,还是上大学的时候习得的。工作不管是开发桌面程序Winform,WPF,还是Web程序,亦或是Office插件,一直使用的C#。在最近的工作中,需要使用C#调用一些C++类库,通常的做法就是把C++类库通过C++ CLI包装一下,然后变成dll直接供C#调用。但是到了.NET Core时代,C++ CLI已经不被支持了,所以唯一的交互方式就是通过P/Invoke,于是看了另外一本书《精通.NET互操作:P/Invoke、C++ Interop和COM.Interop》,发现在.NET与C++进行互操作时有非常多需要注意的地方,一不小心就会有性能问题,且容易出错,当然,这里面涉及到需要掌握一些C++的知识,所以就打算学习一下C++。     要学习一门新语言,当然要找最经典的书本看,然后跟着练习,于是我找到了《Primer C++ 第五版》这本书,我初次接触到C++里面的 …

C++

使用LINQPad实现短平快的功能需求

在平常的开发过程中,我们可能需要写一小段代码来分析某个数据,或者验证某个功能是否实现正确。通常要实现这些小功能,可以在Visual Studio中完成,但从Visual Studio打开启动完成,到开始编写第一行代码,通常需要很多时间 ,LINQPad提供了一种即开即写即编译运行的C#环境,可以用来进行快速的概念验证,以及开发一些短平快的小功能或者需求,非常方便。 …

LINQPad

开盘集合竞价算法的原理与实现

集合竞价是电子撮合交易中的重要撮合方式,通常用来在开盘或者收盘时产生开盘价或者收盘价,或者对于某些流动性差的产品,通过一段时间集中进行撮合,找出能产生最大成交量的价格的方式,(即市场大多数人认可的价格)防止价格被不小心操纵。     中国大陆市场中,由于人口众多,流动性几乎从不缺乏,所以从一开始就是采用把集合竞价生成开盘价和连续竞价高效撮合组合在一体的方式。具体上,沪深交易所都是以集合竞价来场开盘价和收盘价,在收盘价上,如果集合竞价不能产生收盘价,则采用最后一分钟加权平均价(上交所最开始的收盘价是使用的1分钟均价,后来改成了也采用集合竞价的方式产生)。本文对沪深交易所的开盘集合竞价算法作了简单论述和实现。 …

OpenCallAuction MatchEngine OrderBook

如何给自己理发

自3月疫情暴发以来,我已经有很长时间没有出小区了,然而头发仍在不停的生长。头发过长会带来很多烦恼,比如不好打理,看起来乱糟糟,甚至有可能影响大脑散热,恰好家里有一个给小孩理发的电动推头,于是研究并实践了一下如何给自己剪头发,看起来效果还行,这里记录居家自我理发过程中需要注意的地方,希望有所帮助。 …

haircut

给站点图片添加CDN功能以提升访问速度

本博客是基于开源Moonglade系统搭建的,由于贫穷,只购买了一台资源极其有限的云服务器。当文章图片过多时,由于带宽和性能的原因,导致文章加载完成耗时很长,本文提供了将站点图片上传到又拍云并启用CDN功能,然后在Moonglade里设置图片CDN从而极大提升了文章加载的响应速度的一种方法,使得在有限的服务器资源下,可以比较随心所欲的在文章里添加图片。 …

CDN Moonglade UpYun

在WPF中使用ttf字体图标

在Winform时代图标,图标都是在资源文件下创建JPG或者PNG来作为图片实现,但是随着TTF字体图标的普及,图标类型的图片越来越多的被放入到TTF中。 比如fontawesome 、iconfont 等,本文以iconfont为例聊一聊在WPF下如何使用TTF字体作为图标。 …

WPF ico file ttf

为Excel插件增加OCR识别功能

在前面开发一个社区团购微信接龙报表自动生成的Excel插件这篇文章中,介绍了如何开发一个根据买菜供货菜单结合群接龙自动生成统计报表的Excel插件。在那篇文章里,是手动输入购物清单里的商品和价格的,其主要原因是上头给的就是图片,而不是Excel文件。 本文介绍了在.NET程序中如何使用OpenCVSharp4结合PaddleOCR来实现图片里文字和表格的识别,并以WPF和Excel插件的方式将OCR功能引入到程序中,极大的减轻了手动录入的工作量。 …

Excel Development VSTO OCR PaddleOCR PaddleSharp OpenCVSharp4

开发一个社区团购微信接龙报表自动生成的Excel插件

在上海疫情持续下,买菜成了居民生活的一大难题。为了阻止疫情传播扩散风险,政府暂停了商超的线下购物。我所在的奉贤区区政府组织了一些名为“满天星”的社区团购。我报名了本楼的社区买菜志愿者,工作就是根据居委提供了菜单,在本楼微信群里用微信接龙的方式收集大家的买菜需求,为了简化工作量,使用VSTO Excel插件的方法开发了一个报表生成工具,可以根据买菜接龙,直接生成各户居民购买物资的报表,这样极大减少了统计上报的工作量。同时也分享了做了两天社区团购自愿者的一些心得体会。 …

Excel Development VSTO community group-buy

解决WPF中ContextMenu绑定RoutedCommand时第一次无法执行的问题

WPF中RoutedCommand是一个非常常用的功能,他能够将某一命令绑定到多个控件上,比如同一个命令可以绑定到Button,Menu,ContextMenu上,这样避免了重复的代码。     但初次使用RoutedCommand时我就遇到了一个很奇怪的Bug,就是将右键弹出菜单ContextMenu的某一个菜单和窗体上的某个Button同时绑定到了某一个命令上。在程序初次运行时,ContextMenu里面的绑定了命令的菜单是灰色的,不可用,即使设置IsEnable=true,也不行。而Button却是正常的,但在点击Button执行一次命令后,ContextMenu里面的菜单就变得可用了。     在一顿搜索之后发现了这篇文章How to Solve Execution Problems of RoutedCommands in a WPF ContextMenu,完美的解决了这一问 …

WPF ContextMenu RoutedUICommand CommandManager FocusManager

WPF单例应用程序的两种实现

在某些场景下,我们需要应用程序只开启一个实例,本文介绍了WPF中单例应用程序的两种实现,一种是删除App.xaml,手写Main函数来进行启动调度,他的优点是性能相对较好,只需要定义一个Mutex即可,缺点是他放弃了WPF程序中App.xaml的一些默认功能,比如可以存放全局资源样式,没有App.xaml使得在某些情况下,其他的窗体除非手动引用资源或样式,否则得不到设计时支持,这两个缺点都可以通过代码或者设计时标签来回避。另外一种方法是保留App.xaml文件,注册Startup方法,在该方法里启动一个后台线程来监测多次打开的行为,当检测到试图打开多次时,将上次的应用打开,它的缺点是额外多增加了一个工作线程。相比第一种方法来说开销较大,但对于当今的CPU来说,多一个线程处理似乎可以忽略,并且这个线程里面使用的是WaitHandle,实际并不占用太多资源。 …

WPF Single Instance Application

SQLServer中使用TVP和SqlBulkCopy批量插入数据

在有些场景下,我们需要批量插入数据,本文介绍了SQLServer中的两种比较高效的批量数据操作方法,它们是TVP表值类型存储过程以及SqlBulkCopy,他们的共同点是通过传输DataTable作为参数,批量插入数据,不同点在于TVP方法需要SQLServer 2008及以上版本,并且需要预先创建表值类型和存储过程,SqlBulkCopy方法则更简洁,不需要额外创建类型或者存储过程。 …

SQLServer TVP SqlBulkCopy Dapper

在WPF的ViewModel中更新UI界面

凡是做UI界面,不管是Winform也好还是WPF,都只有一个UI线程,我们不能在UI线程中执行耗时的操作,因为这样会阻塞UI线程,是的界面变得卡顿,十分影响用户体验。本文以Prism的MVVM模式为例,通过两个场景: 耗时操作通过异步回调返回值和耗时操作直接返回值两种场景,介绍了如何在ViewModel中执行耗时操作,并更新UI界面。 …

MVVM WPF Prism UI Thread

优雅的生成应用程序图标文件

桌面应用程序通常会选择一个ico文件作为程序图标,这个图标会在快捷方式的时候展示。常用的做法是找一个png文件,把它转为.ico文件,但如果ico文件只有单一分辨率,则系统会根据用户的查看选项,而对这单一图标进行缩放,这种缩放会使得图像模糊或者产生锯齿。且这种做法丢失了ico文件的单个图案,多尺寸,多色板优点。本文介绍了如何正确生成ico文件的方法,让您的应用程序图标在不同的分辨率条件下更美观。 …

ico file

OpenFileDialog中根据文件名过滤选择文件

在应用程序中,如果需要用户选择文件,就会用到OpenFileDialog控件,这个控件可以方便用户来选择文件。它提供了一些属性,其中比较重要的有“Filter”,它能够根据后缀筛选过滤文件。但没办法根据文件名进行进一步筛选,但好在可以使用FileName属性,在里面使用一些通配符来在一定程度上解决这一问题 …

OpenFileDialog

ThinkPad W540硬件升级以及安装Windows11

几年前,朋友送了一台笔记本给我,这笔记本是2014年款的ThinkPad W540,在当年来说,性能还是不错,但是放到现在已然已经过时了,但由于贫穷,于是在手动进行了一些配置硬件配置升级后,只能继续使用。这里记录一下我对这台笔记本的一些升级以及如何在上面安装Windows 11操作系统的。     有了小孩之后,这台笔记本其实放在家里已经很少打开了,上周五碰到单位同事有点事情,需要笔记本操作一下,发现已经放了至少6个月没开机的笔记本无法启动了。怀疑是之前加装的128G的那块启动固态硬盘坏了,应该找不到分区表。于是打算折腾一下,今天终于搞好了。 …

Windows 11 ThinkPad W540

线程创建过多导致产生OutOfMemoryException的问题及优化

今天在线上环境又吃了一个bug,程序之前运行良好,最近在增加了数据量之后,启动的时候就直接报了OutOfMemory的bug,但明明内存占用只有100多M。在查看日志后发现,在调用Thread.Start创建线程的时候报了OutOfMemoryException,这里记录一下如何查找原因以及对应的修改方法。 …

OutOfMemory .NET Thread