RSS 2.0 Feed
2007-08 Entries
摘要:企业服务优化原则中有下面一条原则,最近我优化一个企业服务时,对此有了特别深刻的体验,特整理本篇博客: 使用 COM 可封送的参数如果企业服务组件的方法接受调用方传递数据时所用的参数,强烈建议您尽量使用 COM 和 .NET 之间易于封送的类型,例如: ? Boolean ? Byte、SByte ? Char ? DateTime ? Decimal ? Single、Double ? Guid ? Int16、UInt16、Int32、UInt32、Int64、UInt64 ? IntPtr、UIntPtr ? String 如果仅使用这些类型,且要避免传递其他复杂的类型(例如 structures 或 arrays),.NET 序列化程序可以优化调用处理堆栈,并将调用直接序列化到线缆上(对于 RPC)或到虚拟线缆上(对于 LRPC)。这样,调用的执行速度更快。不过,如果您的方法要求复杂的类型,代码将使用通常的 DCOM 调用堆栈调用,这将产生额外的处理。 以上文字来自: .NET 企业服务性能  我最近优化的这个企业服务是CSDN新积分制论坛帖子列表企业服务缓存。 这个帖子列表缓存工作机制如下: 1、启动一个 ActivationOption.Server 的企业服务(ServicedComponent),这个企业服务是工作在一个独立的服务程序进程。 2、这个企业服务中,通过单件模式启用了一个缓存,缓存了CSDN每个大小论坛的帖子列表。 3、当WEB应用启动时候,把每个论坛,每种帖子列表的帖子都从数据库中获得,然后记录到缓存中。方便以后使用。 4、在优化前,这个版本的新积分制论坛并不是所有CSDN的论坛,有100左右的大小论坛,每个大小论坛又有6种帖子列表,每个帖子列表最多显示满足条件的500条记录。这样,初始化数据大致就需要 100*6*500 大致20万左右的数据需要初始化到帖子列表企业服务缓存。 下面是我做测试的三种情况: 1、优化前我代码逻辑:每一个论坛做一次初始化操作,也就是100个论坛调用企业服务的一个方法100次。 这样的代码逻辑,本地测试环境,完成初始化大致需要130秒左右。 2、我把这个初始化的代码,即从数据库获得并写到缓存的代码搬到企业服务内部执行,外部只需要传递一个简单的论坛编号即可。这样优化后,这个初始化过程大致需要40秒。 3、另外一种方法,我把100个论坛所有帖子列表的数据库都在企业服务外部计算好,然后一次性提交给企业服务,即企业服务这个初始化方法只调用一次,完成这个初始化大致需要190秒左右。 对比我做的上面三个测试情况,我们可以看到,业务逻辑没有发生任何变化,变化的只是企业服务接口参数发生变化了,把一些工作从企业服务外搬到了企业服务内部执行。三种情况对企业服务来说,差别就在于企业服务的参数发生变化了。 上面情况2的企业服务参数最简单,用的是Guid 类型的参数。 情况1和情况3用的是自定义的可序列化的类。 情况1企业服务调用了100次,情况3企业服务只调用了1次。 结论: 1、企业服务的参数要尽量使用 COM 和 .NET 之间易于封送的类型,而不是自己定义的实体和传递其他复杂的类型。 2、企业服务使用自己封装的实体或者复杂的类型,带来的性能损耗,比多次调用企业带来的损耗更厉害(对比情况1和情况3) 参考资料: .NET 企业服务性能...[阅读全文]

posted @ | Feedback (4) | Filed Under [ .net 编程心得 技术随笔 网站开发管理相关内容 ServicedComponent(企业服务) ]

摘要:我们要在这篇文章中将实现的功能: 如上图荧光笔画的地方所示: 我们需要通过编写服务程序的安装程序,把企业服务上面 Run application as NT Service 选择框的进行选中操作。   阅读本文基础: 如果你对企业服务不是很了解,可以阅读我之前写的一系列跟企业服务有关的博客。我书写的跟企业服务有关的系列文章可以访问以下链接。 http://blog.joycode.com/ghj/category/1320.aspx 如果你对编程控制企业服务根本不了解,需要首先阅读我之前写的这篇博客: 编程控制企业服务的行为 本文是在上述文章基础上的加深。   正文 编程控制企业服务的行为 这篇博客中我讲到,我们可以通过遍历 COMAdminCatalogCollection 来寻找到我们需要操作企业服务的某个属性,然后更新这个属性。这种做法适用于大多数编程操作企业服务属性。但是我们上面这个需求就无法用这种方式来作了。 我们遍历 COMAdminCatalogCollection 可以更新的属性时候,我们在微软提供的可操作属性列表(如下链接可以看到)中并没有找到可以设置 Run application as NT Service 的选项。 http://msdn2.microsoft.com/en-us/library/ms686107.aspx 只能看到一个可能跟这个需求有关的属性: ServiceName The service name corresponding to the application configured to run as an NT service. If this value is NULL, the application is not configured to run as an NT service. Otherwise, the configuration information for the service can be found by using the service name. Access:    ReadOnly Type:        String Default:    "" Platform Requirements:   Windows XP, Windows Server 2003 这个属性是只读的,我们又没法设置。   如何解决这个问题呢? 很简单,这个需求不是通过属性来指定的,而是通过 COMAdminCatalog 类的 CreateServiceForApplication 方法。 简单来说,我们就是要安装代码中有以下代码:......[阅读全文]

posted @ | Feedback (4) | Filed Under [ .net 编程心得 技术随笔 ServicedComponent(企业服务) ]

摘要:       对于以前用 Windows Form 来开发客户端程序的程序员,在使用 WPF 开发客户端的程序时,在窗体布局上将是他必须面对的一个坎。        布局产生困惑的一个典型场景如下:        我们在开发WPF窗体时候,我们会发现,当我们把菜单控件(Menu)、工具条(ToolBar、ToolBarPanel)、状态条(StatusBar)这些最常见的页面元素拖动到WPF窗体的时候。我们会发现 WPF 窗体中,这些页面元素可以放置在任何位置,而不是之前 Windows Form 那样:主菜单在最上面,状态条在最下面。        WPF中每一个元素如何布局变得更加灵活了,这样可以让美工更好的设计出更漂亮的页面,但是也会让一些缺乏艺术细胞的技术人员页面布局变得巨难看无比。比如我最近在写个简单的调查系统客户端维护工具,使用WPF程序来开发,这个页面布局的事情,就让我非常头大。        WPF 跟布局有关的控件很多,System.Windows.Controls.Panel 是这些所有布局有关的类的基类。需要注意的是,我们在页面布局上一般都是使用这个类的扩展类来处理布局,而不是使用这个类。这些扩展类包括: System.Windows.Controls.Canvas  (画布)System.Windows.Controls.DockPanel  (停靠布局)System.Windows.Controls.Grid    (表格)System.Windows.Controls.StackPanel   (堆栈布局)System.Windows.Controls.VirtualizingPanel  (虚堆栈布局)System.Windows.Controls.WrapPanel  (覆盖布局)        我自己在使用中觉得:对于我们从Window Form 习惯来的技术人员,使用 Grid    (表格) 布局就可以满足我们绝大多数的布局需求,而且简单。下面我们就来介绍如何使用 Grid 布局控件来进行窗体布局设计。        Grid 布局控件很类似 HTML 标签中的 Table 标签。我们事先把一个区域划分成不同的表格,然后决定,某些控件放在那个表格中,那些控件是要跨多少个表格来放置。比如下面窗体效果,是由后面的XAML文件来实现这个效果的。 这个窗口布局上,我使用了Grid控件 我把这个窗口首先划分成三行三列的一个Grid。如上图我对这个窗体的拆分。 最上面的显示多少条目,以及下拉列表框,以及刷新按钮,被放在第一行,跨三列 未发布的调查表列表框被放在第二行,第一列, 支持来回拖动的GridSplitter被我放在了第二列,第二行 ListView 则被我放在了第二行,第三列 最下面的确定,取消按钮被我放在了第三行,跨了三个列 上述界面效果的XAML文件如下:   <Window    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    x:Class="HongjunGuo.SurveySystem.Client.QuestionnaireList"    Title="调查列表" Height="300" Width="500">    <Grid >        <Grid.ColumnDefinitions>            <ColumnDefinition Width="150"/>            <ColumnDefinition Width="5" />            <ColumnDefinition Width="*"/>        </Grid.ColumnDefinitions>        <Grid.RowDefinitions>            <RowDefinition Height="35"/>            <RowDefinition Height="*"/>            <RowDefinition Height="35"/>        </Grid.RowDefinitions>         <DockPanel Height="30" Name="dockPanel2" Grid.ColumnSpan="3" Grid.Row="0">            <Label>显示多少条目:</Label>            <ComboBox Height="21" Name="comboBox1" Width="120" >                <ComboBoxItem IsSelected="True" >5</ComboBoxItem>                <ComboBoxItem>10</ComboBoxItem>                <ComboBoxItem>20</ComboBoxItem>               ......[阅读全文]

posted @ | Feedback (5) | Filed Under [ .net 编程心得 Vista 相关 .net 3.0 WPF 相关 ]

摘要:昨天和今天,我都在对我之前写的UBB解析代码进行性能优化。优化的结果是:1个具有600多个UBB标签的文本,包含多层UBB嵌套,优化前,解析出这个文本需要2分钟,优化后解析出这个文本需要1秒钟。而这次优化,核心优化的技术只有一点:正则表达式Regex 的构造位置发生变化。下面我就来慢慢来说这次优化。 UBB解析组件的简单介绍 需求: 1、把支持的14个UBB标签解析成不同的Html文本。这14个标签包含:代码高亮标签、禁用UBB标签以及一些通用的UBB标签。 2、一部分UBB 标签支持嵌套的解析,比如对以下文本的解析: [b]1[i]2[/i]3[/b] ,要求2这个文本,需要解析成加粗同时是斜体; 3、一部分UBB标签不支持嵌套的解析,比如:代码高亮的UBB标签括的范围内,任何UBB标签都不起作用。 当然,还有很多其他需求限制,这里只罗列影响我UBB解析算法的一些重要需求。我写的这个UBB代码解析的规范,可以参看以下链接:http://forum.csdn.net/help/ubb.html   我的设计: 先把一段包含UBB标签的文本解析成一个树,树的每一个末梢节点都是不能再继续拆分下去的一段文本,即:其下没有起作用的嵌套UBB标签。然后把这个树的每个节点解析内容合并成一段新的文本。 这个算法的瓶颈在把文本解析成树,解析成树后的计算,系统消耗很少,可以忽略不计。 解析成树的算法,我的设计如下: 先在这个文本中,使用正则表达式从头开始找起,找到第一个系统支持的UBB标签,比如我们找到了一个[b] 文本。然后从找到位置开始,向后,找 [/b] 文本,这两个寻找都是使用的正则来寻找,根据这两个寻找的三种结果,分别进行处理. 然后再用递归算法,不停的循环上述处理逻辑,从而把文本解析成树。   我的代码优化 优化前性能不高的代码: // 在一段文本中,从指定位置开始,找到系统支持的UBB标签文本,比如之前的例子,找 [b]  [i] 这些文本 private bool MatchBeginTag(int beginPos, out UBBCodeFragmentType ubbType, out string ubbParameterValue, out int tagPrePos, out int tagEndPos) {    ......    Regex rx_MatchBeginTag = new Regex(@"\[(?<tagName>[a-zA-Z]+)(=(?<value>[^\f\n\r\t\v\]]*))?\]", RegexOptions.Compiled | RegexOptions.IgnoreCase);    ......} // 从指定位置开始,向后 找指定标签的结束标签 private bool MatchEndTag(int beginPos, string tagName, out int tagPrePos, out int tagEndPos) {    ......    Regex rx_MatchEndTag = new Regex(@"\[/" + tagName + @"\]", RegexOptions.Compiled | RegexOptions.IgnoreCase);    ......} 上述两个函数分别实现之前说的两个功能,这两个函数会被频繁的递归调用,比如我之前说的场景,600多个UBB标签的文本,这两个函数会被600次的调用到。   我的优化方法 我通过使用 JetBrains dotTrace 3.0 工具,看到 Regex 的构造函数被频繁的调用,累计调用花费的时间非常巨大,我在这里对它进行代码调整. 对于 MatchBeginTag 函数, 由于它用的 Regex rx_MatchBeginTag 是固定的,很简单,我把这个对象放在函数体之外,把它定义成静态成员,这样它只需要构造一次,改造成如下代码方式: private......[阅读全文]

posted @ | Feedback (12) | Filed Under [ .net 编程心得 ]