TKey

【Orleans开胃菜系列2】连接Connect源码简易分析

穿精又带淫゛_ 提交于 2020-08-07 10:59:59
【Orleans开胃菜系列2】连接Connect源码简易分析 简要说明 //连接代码。 using ( var client = await StartClientWithRetries ( ) ) { } 从方法看,只是一个简单允许重试的启动客户端。追踪进去会发现关于重试逻辑的实践,Socket编程的实践,基于内存的消息队列的实践,依赖注入。再看源码的基础上,最好能配合一些理论书籍来看。理论指导实践,实践反馈理论,才是技术成长的步骤。 这篇文章只涉及Connect所引用方法的部分说明,一步一步来加深理解。 本来我是打算把orleans研究透之后再来写一篇,但看了一周之后,发下connect里面调用了很多类,每个类又有很多方法,这样下去没有尽头,到最终估计什么也写不成。 分析源码本来就是循环渐进的过程,也是一个熟悉框架/原理/实践的过程。直接跳过这个步骤,必然损失良多。所以这部分就叫开胃菜吧。在查看connect过程,会越来越接触到各种知识。 本篇暂不涉及数据持久化,主要依赖.netcore内置方法操纵内存实现。 您会接触到的扩展知识 扩展知识之Timer&TimerQueue Timer Timer 在设置的间隔后生成事件,并提供生成重复事件的选项 TimerQueue 时间队列 扩展知识之信号量 SemaphoreSlim SemaphoreSlim 实现 //信号量

AVL树(二)之 C++的实现

佐手、 提交于 2020-08-05 04:40:33
概要 上一章 通过C语言实现了AVL树,本章将介绍AVL树的C++版本,算法与C语言版本的一样。 目录 1. AVL树的介绍 2. AVL树的C++实现 3. AVL树的C++测试程序 转载请注明出处: http://www.cnblogs.com/skywang12345/p/3577360.html 更多内容 : 数据结构与算法系列 目录 (01) AVL树(一)之 图文解析 和 C语言的实现 (02) AVL树(二)之 C++的实现 (03) AVL树(三)之 Java的实现 AVL树的介绍 AVL树是高度平衡的而二叉树。它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。 上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1;而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1)。 AVL树的C++实现 1. 节点 1.1 AVL树节点 template < class T> class AVLTreeNode{ public : T key; // 关键字(键值) int height; // 高度 AVLTreeNode *left; // 左孩子 AVLTreeNode *right; // 右孩子 AVLTreeNode(T value, AVLTreeNode *l,

Java数据结构和算法(十一)——红黑树

怎甘沉沦 提交于 2020-07-28 20:38:11
  上一篇博客我们介绍了二叉搜索树,二叉搜索树对于某个节点而言,其左子树的节点关键值都小于该节点关键值,右子树的所有节点关键值都大于该节点关键值。二叉搜索树作为一种数据结构,其查找、插入和删除操作的时间复杂度都为O(logn),底数为2。但是我们说这个时间复杂度是在平衡的二叉搜索树上体现的,也就是如果插入的数据是随机的,则效率很高,但是如果插入的数据是有序的,比如从小到大的顺序【10,20,30,40,50】插入到二叉搜索树中:      从大到小就是全部在左边,这和链表没有任何区别了,这种情况下查找的时间复杂度为O(N),而不是O(logN)。当然这是在最不平衡的条件下,实际情况下,二叉搜索树的效率应该在O(N)和O(logN)之间,这取决于树的不平衡程度。   那么为了能够以较快的时间O(logN)来搜索一棵树,我们需要保证树总是平衡的(或者大部分是平衡的),也就是说每个节点的左子树节点个数和右子树节点个数尽量相等。红-黑树的就是这样的一棵平衡树,对一个要插入的数据项(删除也是),插入例程要检查会不会破坏树的特征,如果破坏了,程序就会进行纠正,根据需要改变树的结构,从而保持树的平衡。 1、红-黑树的特征   有如下两个特征:   ①、节点都有颜色;   ②、在插入和删除的过程中,要遵循保持这些颜色的不同排列规则。   第一个很好理解,在红-黑树中

深入解读Dictionary

徘徊边缘 提交于 2020-07-27 03:55:31
Dictionary<TKey,TValue> 是日常.net开发中最常用的数据类型之一,基本上遇到键值对类型的数据时第一反应就是使用这种散列表。散列表特别适合快速查找操作,查找的效率是常数阶O(1)。那么为什么这种数据类型的查找效率能够这么高效?它背后的数据类型是如何支撑这种查找效率的?它在使用过程中有没有什么局限性?一起来探究下这个数据类型的奥秘吧。 本文内容针对的是 .Net Framework 4.5.1 的代码实现,在其他.Net版本中或多或少都会有些差异,但是基本的原理还是相同的。 本文的内容主要分为三个部分,第一部分是从代码的角度来分析并以图文并茂的方式通俗的解释Dictionary如何解决的散列冲突并实现高效的数据插入和查找。第二部分名为“眼见为实”,由于第一部分是从代码层面分析Dictionary的实现,侧重于理论分析,因此第二部分使用windbg直接分析内存结构,跟第一部分的理论分析相互印证,加深对于这种数据类型的深入理解。最后是从数据结构的时间复杂度的角度进行分析并提出了几条实践建议。 本文内容: 第一部分 代码分析 散列冲突 Dictionary图文解析 Dictionary的初始化 添加第四个元素 第二部分 眼见为实 添加第一个元素后的内存结构 添加第四个元素后的内存结构 第三部分 时间复杂度分析 实践建议 散列冲突 提到散列表,就不能不提散列冲突

深入解读Dictionary

泪湿孤枕 提交于 2020-07-25 00:57:43
Dictionary<TKey,TValue> 是日常.net开发中最常用的数据类型之一,基本上遇到键值对类型的数据时第一反应就是使用这种散列表。散列表特别适合快速查找操作,查找的效率是常数阶O(1)。那么为什么这种数据类型的查找效率能够这么高效?它背后的数据类型是如何支撑这种查找效率的?它在使用过程中有没有什么局限性?一起来探究下这个数据类型的奥秘吧。 本文内容针对的是 .Net Framework 4.5.1 的代码实现,在其他.Net版本中或多或少都会有些差异,但是基本的原理还是相同的。 本文的内容主要分为三个部分,第一部分是从代码的角度来分析并以图文并茂的方式通俗的解释Dictionary如何解决的散列冲突并实现高效的数据插入和查找。第二部分名为“眼见为实”,由于第一部分是从代码层面分析Dictionary的实现,侧重于理论分析,因此第二部分使用windbg直接分析内存结构,跟第一部分的理论分析相互印证,加深对于这种数据类型的深入理解。最后是从数据结构的时间复杂度的角度进行分析并提出了几条实践建议。 本文内容: 第一部分 代码分析 散列冲突 Dictionary图文解析 Dictionary的初始化 添加第四个元素 第二部分 眼见为实 添加第一个元素后的内存结构 添加第四个元素后的内存结构 第三部分 时间复杂度分析 实践建议 散列冲突 提到散列表,就不能不提散列冲突

看看Delphi中的列表(List)和泛型

耗尽温柔 提交于 2020-05-08 21:19:26
前言 最开始学习数据结构的时候,链表,堆栈,队列,数组,似乎只是一堆概念,随着使用中慢慢接触,其对应的模型,功能,一个个跃到眼前,变成了复杂模型数据处理中的最重要的部分。---By Murphy 20180424 1,列表 Delphi中的列表有很多,从数据结构上可以分作:TList(数据链),TQueue(队列),TStack(堆栈),TDictionary(字典表)等等; 而从功能上又可以分作TList(列表),TObjectList(对象列表),TComponentList(组件列表),TStringList(字串列表),TClassList(类列表)。 列表的数据结构性,决定了列表的基础方法,基本都是以增删改查,计数,排序为主;而功能列表中,进一步增强了对每个节点元素的检查和限制,从而增加了针对这种数据类型的更贴合的功能,例如:对象的自动销毁,或仅结构移除,构建排序比较规则等等。现在就让我们看几种具有代表性的列表 a,TList 我们首先来看看TList在DelphiRX10中的源码定义 TList = class(TObject) private FList: TPointerList; FCount: Integer; FCapacity: Integer; protected function Get(Index: Integer): Pointer;

Core源码(一) ConcurrentDictionary

情到浓时终转凉″ 提交于 2020-05-02 04:17:36
先贴源码地址 https://github.com/dotnet/corefx/blob/master/src/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs .NET CORE很大一个好处就是代码的开源,你可以详细的查看你使用类的源代码,并学习微软的写法和实现思路。   这里我对.net core中ConcurrentDictionary源码进行了分析,里面采用了Volatile.Read和write(volatile作用:确保本条指令不会因编译器的优化而省略,且要求每次直接从内存地址读值,而不走寄存器),然后也使用了lock这种混合锁,而且还定义了更细颗粒度的锁。所以多线程使用ConcurrentDictionary集合还是比较好的选择。 本来想把本篇放到我的《 C#异步编程系列 》,不过后来感觉那个系列写的已经算是收尾了,而且以后还会有写更多core源码分析的文字,所以就单独新增一个系列把。 ConcurrentDictionary内部私有类 先上源码,再仔细聊 /// <summary> /// Tables that hold the internal state of the ConcurrentDictionary /// ///

ConcurrentDictionary

可紊 提交于 2020-05-01 07:22:40
ConcurrentDictionary ConcurrentDictionary一大特点是线程安全,在没有ConcurrentDictionary前 在多线程下用Dictionary,不管读写都要加个锁,不但麻烦,性能上也不是很好 微软得出的结果是默认的锁的数量是CPU核的个数,这个线程池默认的线程数量一样。随着Dictionary的扩容,锁的个数也可以跟着增加,这个可以在构造函数中自己指定。 private sealed class Tables { internal readonly Node[] _buckets; // bucket成了这样,也就是ConcurrentDictionary可以认为是一个bucket数组,每个Bucket里又由next来形成链表 internal readonly object[] _locks; // 这个就是锁的数组了 internal volatile int[] _countPerLock; // 这个是每个锁罩的元素个数 internal Tables(Node[] buckets, object[] locks, int[] countPerLock) { _buckets = buckets; _locks = locks; _countPerLock = countPerLock; } } /

Java数据结构和算法(十一)——红黑树

女生的网名这么多〃 提交于 2020-04-26 15:54:04
  上一篇博客我们介绍了二叉搜索树,二叉搜索树对于某个节点而言,其左子树的节点关键值都小于该节点关键值,右子树的所有节点关键值都大于该节点关键值。二叉搜索树作为一种数据结构,其查找、插入和删除操作的时间复杂度都为O(logn),底数为2。但是我们说这个时间复杂度是在平衡的二叉搜索树上体现的,也就是如果插入的数据是随机的,则效率很高,但是如果插入的数据是有序的,比如从小到大的顺序【10,20,30,40,50】插入到二叉搜索树中:      从大到小就是全部在左边,这和链表没有任何区别了,这种情况下查找的时间复杂度为O(N),而不是O(logN)。当然这是在最不平衡的条件下,实际情况下,二叉搜索树的效率应该在O(N)和O(logN)之间,这取决于树的不平衡程度。   那么为了能够以较快的时间O(logN)来搜索一棵树,我们需要保证树总是平衡的(或者大部分是平衡的),也就是说每个节点的左子树节点个数和右子树节点个数尽量相等。红-黑树的就是这样的一棵平衡树,对一个要插入的数据项(删除也是),插入例程要检查会不会破坏树的特征,如果破坏了,程序就会进行纠正,根据需要改变树的结构,从而保持树的平衡。 1、红-黑树的特征   有如下两个特征:   ①、节点都有颜色;   ②、在插入和删除的过程中,要遵循保持这些颜色的不同排列规则。   第一个很好理解,在红-黑树中

C#效率优化(1)-- 使用泛型时避免装箱

让人想犯罪 __ 提交于 2020-04-18 10:03:53
  本想接着上一篇详解泛型接着写一篇使用泛型时需要注意的一个性能问题,但是后来想着不如将之前的详解XX系列更正为现在的效率优化XX系列,记录在工作时遇到的一些性能优化的经验和技巧,如果有什么不足,还请大家多多指出;   在使用集合时,通常为了防止装箱操作而选择List<T>、Dictionary<TKey, TValue>等泛型集合,但是在使用过程中如果使用不当,依然会产生大量的装箱操作;   首先,将值类型的实例当做引用类型来使用时,即会产生装箱,例如: int num = 10 ; object obj = num; IEquatable < int > iEquatable = num;   其次,对于自定义结构,在正常使用时,通常需要注意一些误装箱的操作: public struct MyStruct { public int MyNum; }   对该结构MyStruct的实例调用基类Object中的方法时,都会进行装箱操作,对于静态方法(Equals、ReferenceEquals)很好理解,对于实例方法,在CLR调用实例方法时,实际上会把调用这个方法的对象当作第一个参数传入实例方法,而基类Object中的实例方法都会将Object类型的对象作为第一个参数,因此也会发生装箱,这其中的实例方法包括GetType和虚方法Equals、GetHashCode、ToString