Web Analytics
yangyang

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

All Posts


使用命名管道进行进程间通讯

在某些情况下,我们需要在本机上的多个进程间进行通讯(inter process communication,IPC)。进程间进行通讯的方式有很多种,比如共享内存、TCP/IP、命名管道(Named Pipes)、Windows消息等等。本文主要介绍命名管道这种进程间通讯的使用方法。 …

NamedPipe IPC

从Dictionary中key为大小写不敏感的字符串类型说起

本文由一个在Dictionary中使用String作为key,且支持大小写不敏感匹配的例子来说明Dictionary的内部原理。由Key获取hash值是Dictionary实现的关键。在Dictionary声明的时候,可以通过构造函数传递IEqualityComparer参数来指定比较器,通过该对象来获取哈希值。如果不提供这个参数,则会在内部判断Key是否实现了IEquatable泛型接口,如果提供了,则使用该泛型接口中定义的GetHashCode来获取哈希值,否则会根据Key的类型生成一个通用的EqualityComparer,这个通过的EqualityComparer的参数是object类型,所以如果Key的类型为结构体,则必须为其实现IEquatable泛型接口,否则就会产生装箱从而严重影响性能。 …

Dictionary Hash StringComparer IEquatable IEqualityComparer

解决WinForm中Chart控件偶发的一言不合就报错画红叉的问题

在WinForm中,使用自带的System.Windows.Forms.DataVisualization.Charting图表控件绘图时,在极其偶然的情况下,由于一些数据或者参数不对,会导致图表绘图区出现一个大大的红色叉叉,同时会弹出报错窗体。这个问题在我司的一个程序中非常罕见,且不容易重现,最近在处理这个问题时,通过控制变量,使得这一问题比较容易重现,从而为找到问题打开了突破口,这里记录一下。 …

CandleStick MSChart Red-Cross StackOverflow

C++内存管理基础

本文也是候捷《C++内存管理机制》的笔记,介绍了C++原始内存分配的基本方法,优缺点,以及介绍了一个简单的内存池,虽然在Modern C++中已经不建议直接管理内存分配后的指针,而是采用智能指针的方式。但是这些只是对原始内存分配的一些包装或处理,所以这里记录一下。 基本方式 《Effective C++》这本书开篇就指出,C++由几大部分组成: C语言部分。C++是以C为基础,C++经过编译器处理后就是C语言。在C++中仍然保留了很多C语言的用法,比如区块(blocks)、语句(statement),数组(arrays)、指针(pointer)等等。所以C语言中的一些内存分配方法,在C++中仍然能够使用。 面向对象,就是C with Class,包括类、封装、继承、多态等等。 模版,Template C++是C++泛型编程的一部分。这一点跟C#中的泛型编程个人感觉区别巨大。但C++中的模版 …

memory management memory pool allocator embedded pointer

C++中的模版模版参数和模版别名的使用

最近在看候捷的C++系列视频教程,其中有一个例子讲到了使用迭代器特性(iterator_traits)和使用模版模版参数(template template parameter)以及模版别名(alias template)来完成同一件事情,非常的经典,我这里记录一下。 事情的起因 事情的缘由是要比较在不同类型的容器类型(vector、deque、set等等)中,对象是否有moveable的相关构造函数 对容器的各种操作性能的影响。所以要编写一个通用的模版方法,允许接受不同的模版参数,以及不同的数据类型,并能输出调用各种操作(拷贝构造,移动构造,赋值构造)耗费的时间等的时间。 为了方便进行,这里编写了两个简化版本的String类,一个名为MyString的类带有各种移动构造,拷贝,赋值函数(Big Five) #include #include # …

template template parameter alias template iterator traits

“异常”应该仅用于真正的异常情况而不应将其当作正常处理流程来使用

在《Writing High-Performance .NET Code》这本书中,作者指出,抛出“异常”(Exception)的开销十分高昂,很大一部分原因是.NET的异常对象中包含了丰富的信息,“异常”必须是为真正的异常情况服务,在这种情况下性能可以退居其次。 作者还举了例子,说明了三个事实: 抛出“异常”的方法比空方法慢了数千倍。 “异常”抛出的层数越深,速度就越慢。 和只用1个catch相比,多个catch语句的影响比较轻微,但仍然影响很明显。 使用catch捕获异常的开销可能不大,但是要访问Exception对象的StackTrace属性开销可能会非常高。因为需要由“异常”指针重建调用栈,并转译成可读文本。作者反复强调,“异常”应该仅用于真正的异常情况,如果将“异常”作为正常的处理流程来使用,会让程序毫无性能可言。 …

Exceptions

.NET中几种名字包含Dictionary的数据结构

在.NET Core的源代码中,除了常用的Dictionary、ConcurrentDictionary之外,还有几种名称包含Dictionary的数据结构,它们是ListDictionary、OrderedDictionary、SortedDictionary、HybirdDictionary和StringDictionary。这些个杂牌Dictionary用得很少,不看源代码可能还不知道😂。表面上看,好像都是Dictionary,但研究发现其内部实现却大不相同。 …

ListDictionary OrderedDictionary SortedDictionary HybridDictionary

.NET Core中Dictionary的实现

Dictionary是一种存储键值对的数据结构,可以根据Key快速查找对应的Value,它的内部实现原理其实很简单,在浅谈算法和数据结构: 十一 哈希表这篇文章中有详细介绍,但实际的原理和工程实现可能有所不同,在.NET中有.NET Framework和.NET Core的两个版本,大体相同,但细节上有所区别。这里以.NET Core中的Dictionary源码为例,来说明Dictionary的实现细节。 …

Hashtable Dictionary

多线程环境下使用HashSet抛出NullReferenceException异常的分析

在.NET中有普通集合类型比如Queue,Dictionary等,也有对应的并发集合比如ConcurrentQueue,ConcurrentDictionary,顾名思义,前者是非线安全的,如果要在多线程环境下使用,需要自己加锁,后者则是线程安全的。 线程安全是有代价的,那就是会影响效率。在有些时候下,应用场景很少写,但读很非常频繁,在允许“脏读”的情况下,是不是直接使用普通的集合类型就可以呢,答案是可以,但是需要非常慎重,否则可能会抛出异常。今天我就遇到了这个问题。 场景 有个类SymbolManager,在内部有一个HashSet,这个HashSet里保存了一系列代码,程序会在每天早上的9点重新加载本地文件里的代码到这个HashSet集合里,同时这个类对外提供了一个IsSymbol 方法,以判断某个代码是否在此HashSet中。 class SymbolManager …

HashSet

记一次.NET程序内存暴涨分析

大约在上个月,利用WinDbg找到了软件中的一个存在很久的内存会暴涨的bug,说起来也是巧合,这里记录一下。 在描述问题之前,我想提一下,软件开发中寻找bug的正确思路和方法,这也是从我领导那里学到的严谨态度,并且在工作中体会最深的。 …

WinDbg Memory Leak