`
wooce
  • 浏览: 184250 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

技术聊天记录: 关于TAttributeSet减少lookup的改进方法的讨论

    博客分类:
  • C++
阅读更多
wooce:
我仔细思考了一下:
1)  如果不能把Server端和Client端的程序放在一起编译,  或者是由程序员定义一个include某AttributeSet中
会出现的所有键值的enum放在某头文件里,  在server端和client端所有用到某attributeset的地方都引用这个头文件,  总之必
须让所有用到attributeset的地方都知道这个attributeset里所有可能的键值, 要在编译时就完全决定
Get("abc")是Get  AttributeSet中的第几项, 是难以做到的. 
不论编译器(或发明/下载的特殊的程序预处理器)如何地聪明,  若单独编译client端的程序,  因为
client端不一定用到server端put入的所有key值,  所以server端发送过来的attributeset里存在有
编译client程序时未知的key,   编译client程序时要把这些未知的字符串类型的key映射到AttributeSet
中的某个位置上,  不论我们去找多少花哨的程序设计技巧, 实质都要归结为把一个字符串集合中的某个字
符串唯一映射到一个整数上(不同的字符串必须映射到不同的整数) ,  显然并不存在这样的映射, 那些如
HASH方法总难免把几个字符串映射到同一个整数上. 
2)  如果不想采用在server端和client端所有用到某attributeset的地方都引用包含其中的所有键值的头文件的方法,
又想提高lookup的效率而同时保持原来的弹性,  显然必须修改我们的通讯协议,  client端在接收某个AttributeSet的时侯, 如果
此前从未接收过此attributeset,  则必须和server端进行协商,  建立一张attributeset的各个key在client端的
Get()所用的整数index值和server端以后发送过来的此attributeset的相对应的存储位置的对照表, 这样client端在Get("abc")
时实际上是执行取Values[ convert[i] ] 的操作,  不再需要lookup字符串了,  提高了效率.
在一些细节上:  
    现在的使用attributeset的程序一般是:
OnRequest()
{
....
    TProtocol *pProtocol;
    XNew(pProtocol, TProtocol(....));
    pProtocol->SvrReceive(comm, asRequest);
    TAttributeSet asRequest, asResponse;
    int cmd = asRequest.Get("Cmd").AsInt();
    asRequest.Get("abc").AsString();
    asRequest.Get("efg").As....();
....
}
    可以看出要保持这种写法的弹性, 又能在第一次GET一个attributeset的时侯插入和server协商建立对照表的代码有点
麻烦. 
    我觉得比较好的改法是变上面的pProtocol->SvrReceive(comm, asRequest);为asRequest.SetCommProtocol(comm,pProtocol);
里面并不执行通讯操作,  在其后执行的第一条asRequest.Get("...")代码中, 根据某变量知道还未建立对照表,  然后调用
类似pProtocol->SvrReceive(comm, asRequest);原来的代码get到server端发来的attributeset的全部内容和全部key,  由于在编译
第一条Get语句的时侯并不知道后面的其他Get语句的键的字符串,  所以此时对照表还不能完全建立的,  只能先
        static int i=0;
        存储位置j = find(attributeset from server, "Cmd") ;
        对照表convert.Put(i, j);
        return Values[ convert[i++] ];
然后在第二条
asRequest.Get("...")上,  执行上面同样的代码(不需和Server协商了) ,
最后当get完所有key的时侯, 就知道对照表已建立好.  但如果client端不需要get其中所有的key的时侯,  那就需要在所有Get()方法后
加个asRequest.End()的方法来显式标志对照表已建立了.

XXX:


其实昨天我说那个想法的意思是,attributeset可以考虑的优化方面的东西很多,那样只是其中的一个,而且不一定可行的,我是想让你具体想想是否还有其他想法,或者那个想法是否可行:
1.attributeset目前key在程序中都是通过#define做的,实际上,
    1.1.可以考虑直接提供int类型的key(特别是内部使用的场合)
    1.2.提供const char * 的接口方式
2.由于目前程序还没有被广泛使用,所以可以考虑修改通信协议来优化
3.实际上目前attributeset的存贮结构决定了:
    3.1.即使有key lookup的优化,实际上每次还需要对buffer进行parse,知道每一块的物理位置(就时说即使知道"abc"就是1也需要知道1对应在物理buffer的哪里
    3.2.如果需要parse实际上在parse的时候已经可以做完key的lookup了,而字符串的比较在parse过程中,实际上不会比int比较慢太多的,所以简单这样的优化意义不大
    3.3.基于3.1.,3.2.实际上要做key lookup的优化,最终必须改协议增加索引表,这样实际上就是tim说的问题了,而反过来实际上通过1.1.的方式就可以优化了部分的过程,所以不一定需要做那么复杂的事情.
4.由于"内存分配"操作相对而言是比较耗费资源的(相对strcmp之类的东西),所以减少内存分配的次数实际上是优化的一个原则,这个已经体现在了TRefAttributeSet里面了,但是我觉的这样反而不好,多了一个东西别人反而不知道应该用哪一个,所以需要考虑能否把两个东西合并成为一个优化了的TAttributeSet
5.下面是我的一些想法:
    5.1.确定attributeset的使用的限制:
        至少有:每一个数据项的长度不大,如果数据项可能比较大的,通过其他方式包装,Tprotocol可以兼容
    5.2.AttributeSet内部同时存在两种态性(两种数据):一种是打包好的数据(a),一种是分散的hash或者其他的方便管理的数据(b):
        所有Get的操作,如果b里面有,就返回b里面的,否则就在a中直接查找返回,同时根据某些规则判断(比如attribute有多少)是否加入b中
        如果Put的操作,直接增加在hash列表中,
        当需要输出的时候,merge两部分数据:如只有b,就通过b生成a,如果只有a,就直接输出,否则就以b优先,和现有的a比较,生成新的a然后输出
        这样做的目的是,实际上现在很多数据get回来之后只是pass给别人,或者自己只用一两项,所以没有必要全部parse出来,另外如果只有10个以下的attribut实际上直接查找比建立hash或者list还要快
    5.3.为了优化查找,可以考虑生成的数据包里面的数据已经通过排序或者hash的规则放置:
        因为毕竟打包的操作肯定是最少的,所以这个地方的处理复杂也是可以理解的:
        考虑按hash放置,提供一个hash的index在整个attributeset前面,然后可以直接根据hash找到对应的列表然后顺序查找(打包的数据分成桶,由于数据是每次打包完成,所以不需要太复杂的管理,否则就变成DB了:))
        考虑按key排序,同时每一个Attribute附上二分查找需要的信息(其实就是一些offset,保证可以找到key值为中间的那个attribute)
       
    由于我对attributeset的了解有限,所以希望你对我上面说的东西提提意见,最好是提出更新的想法

Wooce:

1.  在打包数据里 lookup的时侯我们执行的是strstr,  并不是strcmp,  ,      我测试了一下,     已经有char p[1024]; 的情况,  p1 = new char[1024]; memcpy(p1,p)的开销不见得比strstr( p,  "...")的开销高,   特别是所lookup的字符串是在char p[1024]; 的后半段或者根本不存在的情况,    所以lookup执行strstr的开销也不能忽视,   不过幸好打包数据的格式是keyname1  ->    value1.size   ->    value1.content   -> ....  ,  所以我们可以凭借value1.size 移动跳过一大段数据,  只会比较keyname,   而不是strstr( 打包数据,key)这么做,    所以你说的节约parse的开销还是有效的.

2.   同时存在两种态性的数据的想法的确很有创造性,    //admire. 
     1)   这想法应该确能起到优化性能的作用.
     2)  存在以下复杂性:
         a.   嵌套情况,  即一个attributeset里面有另一个attributeset作为其attribute的情况. 
         b.   方便管理的结构b如果象TAttributeSet那么以HASH存储,  可能往b里存数据后,  需要处理一个不完整的树的情况.  虽然很少出现, 但既然没有做限制,
       我们就必须对其做出考虑.

3.    现在的协议的打包数据是按      keyname1  ->    value1.size   ->    value1.content   ->    keyname2   -> value2.size   ->    value2.content ....  的形式依次存储的,  本来keyname等本身就是作为索引的,   现在这样的打包方式, 使我们不知道这些keyname本身的位置,   所以你又提出来在整个打包数据前面再加一个这些keyname的hash索引的方法.   
       其实我想,    可以干脆把打包数据分成纯粹的索引和纯粹的attribute value数据两部分. 
       即:      打包数据  =  [索引][纯数据]
                 索引  =  keyname1  offset1  keyname2  offset2  .....     
                 纯数据 =  value1.content   value2.content   value3.content   ......
      索引的keyname1 offset1 .....   的前面是仍然可以再加上你所说的HASH索引的.
      这样带来的好处:  
           1)  接收attributeset方可以快速获得一个长度不会太大的包含了所有keyname和其offset的索引数据,  不会出现在一个很大的打包数据里移动的情况(在put了落入同一HASH桶的多个keyname进去attributeset的情况会如此).    这样你所说的5.1的使用限制应该可以避免. 
           2)  接收attributeset方要修改attributeset,  再put入新的attribute到其中的情况,   很显然,   在考虑按key排序的时侯,   我们在上面所说的索引数据中排序, 并且把新put入的值简单直接加到纯数据段的后面,    要比把一个key和value混合间杂的数据重新组织排序容易得多,  也会有较好的性能.
           3)  发送attributeset方以put多次创建一个 attributeset的时侯,   如果以原来的格式,  我们可以知道必须把每次put入的数据先clone进"易管理的结构b",   最后打包的时侯又必须依次从"易管理的结构"里取出来clone到生成的打包数据里面,     而按纯索引和纯数据分开的格式,  我们每次put入的数据是可以一次性直接clone进最后所生成的打包数据的.    所以又节省了一笔开销.  
           4)   在嵌套的情况,    我们仍然可以把索引定义成比较线性化的规整的形式.   使编程简单.
2
0
分享到:
评论

相关推荐

    Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker

    Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker 一通百度,发现原来是dns服务器的错误,把服务器改成8.8.8.8或者114.114.114.114即可 具体做法: vim /etc/...

    修复Linux异常自动重启问题

    这几天训网络最困扰我的问题就是服务器...EXT4-fs error (device sda1): ext4_lookup:1593: inode #6004222: comm trash-expunge: deleted inode referenced: 6004301 类似这样的错误,看样子是sda1磁盘文件系统的问题

    解决docker报错dial tcp lookup registry-1.docker.io

    解决docker报错dial tcp lookup registry-1.docker.io

    LOOKUP函数处理内存数组

    在Excel中,LOOKUP函数是一种强大的工具,尤其在处理内存数组时,它的功能更为突出。内存数组,也称为工作区数组或动态数组,是Excel在内存中存储的一组数据,无需预先定义单元格范围,这使得它在进行复杂计算和数据...

    lookup函数的使用

    "Excel Lookup 函数的使用和经典查找方式" Lookup 函数是 Excel 中最常用的查找函数之一,它可以帮助用户快速地查找和匹配数据。本文将详细介绍 Lookup 函数的用法、语法、参数意义、应用实例,以及经典的条件查找...

    requestUtils lookup方法简介

    requestUtils lookup方法简介

    【含源码和addin】RevitLookup 2020

    【亲测可用】Revit 2020 Lookup Tables是Revit表格查找工具,是revit开发必不可少的一个组件,需要的朋友可以下载! 用法:将RevitLookup.addin和RevitLookup.dll放到C:\ProgramData\Autodesk\Revit\Addins\2019下...

    Revit Lookup2017-2020.zip

    6. **提高效率**:对于Revit的二次开发者来说,Revit Lookup极大地提高了工作效率,减少了在源代码和Revit模型间反复切换的时间。 7. **社区支持**:由于Revit Lookup是开源工具,开发者社区对其持续维护和更新,...

    dnslookup:简单的命令行实用程序,可对指定服务器进行DNS查找

    dnslookup 简单的命令行实用程序即可进行DNS查找。 支持所有已知的DNS协议:纯DNS,DoH,DoT,DoQ,DNSCrypt。 如何安装 使用自制程序: brew install ameshkov/tap/dnslookup 来自来源: go get github....

    RevitLookup-2021.0.0.13

    RevitLookup是一款强大的Revit插件,主要用于Revit二次开发中的调试和分析工具。它能够帮助用户在Revit环境中深入洞察模型元素的属性和结构,从而更好地理解和优化BIM(建筑信息模型)项目。RevitLookup-2021.0.0.13...

    pe_lookup:与'puppet lookup'命令类似,但带有分类器

    pe_lookup 目录 描述 该模块提供一个Puppet命令puppet pe lookup ,该命令输出在Hiera和/或Classifier中定义的键(类参数)。 设置 在主要主机上安装此模块。 用法 以root身份在Primary Master上运行puppet pe ...

    EXT 的一个例子lookup

    - `GridEditor.js`: 顾名思义,这可能包含了关于Grid编辑的EXT组件或功能,可能涉及到`lookup`在Grid中的实现。 - `combo.js`: 这个文件可能包含了关于ComboBox的EXT组件扩展或定制,与`lookup`中使用的ComboBox...

    用友手册资料:ECA-LOOKUP DATA手册.pdf

    本手册主要介绍了 Lookup Data 的安装、配置、使用和常见问题解决方法。 目录 Lookup Data 用户手册主要包括以下几个部分: 1. 产品介绍 2. 应用专题 3. 安装后的客户端 4. Office 环境 5. 常见问题 产品介绍 ...

    RevitLookup-2020.0.0.4.rar

    7. 错误处理和日志记录:为了确保插件的稳定性和可靠性,Revit Lookup会包含错误处理代码,以及用于记录和分析问题的日志系统。 通过深入研究Revit Lookup的源代码,开发者可以提升Revit插件开发的技能,更好地理解...

    RevitLookup2021.rar

    5. **跨版本兼容**:RevitLookup2021表明这个工具已经更新到支持Revit 2021版本,这意味着它应该能够与Revit 2021的API接口无缝配合,提供对新功能和改进的访问。 安装步骤如下: 1. 下载并解压缩RevitLookup2021....

    介绍用虚拟机安装Linux系统.rar

    在IT领域,虚拟化技术是不可或缺的一部分,它允许我们在一台物理机器上运行多个独立的操作系统实例。本教程将深入探讨如何使用虚拟机安装Linux系统,为初学者提供一个安全、可控制的学习环境,同时不影响现有的...

    Using a TopComponent's Lookup

    你可以通过调用`setLookup`方法提供一个`Lookup`实例,或者通过重写`createLookup`方法创建一个新的`Lookup`。 2. **关联Lookup到TopComponent**:确保你的`TopComponent`类扩展了`Lookup.Provider`,这样就可以为`...

    EXCEL中lookup函数的经典查找方式.doc

    EXCEL 中 Lookup 函数的经典查找方式 Lookup 函数是 Excel 中最常用的两个查找函数之一,另一个是 VLOOKUP 函数。Lookup 函数可以用来查找指定的值在表格中的位置,并返回对应的结果。Lookup 函数有两种语法形式:...

    RevitLookup 2020.0.0.1

    RevitLookup的使用方法通常包括以下步骤: 1. **安装**:通过运行msi安装包,将RevitLookup集成到Revit环境中。 2. **启动**:在Revit中,通过插件菜单或快捷键启动RevitLookup。 3. **选择元素**:在Revit模型中...

Global site tag (gtag.js) - Google Analytics