[转载]远程访问数据库进行配置

mikel阅读(1175)

[转载]远程访问数据库进行配置 – weifield – 博客园.

团队间开发,需要使用同一个数据库服务器,所以大家必须都可以使用IP地址来访问数据库。

通常访问数据库的方式,有三种

1、

直接访问本地数据库,在服务器名称里,输入“ . ” ,这个圆点。

2、

直接访问本地数据库,在服务器名称里,输入本机名称

3、

在本地或者在远端进行访问,在服务器名称里输入,SQLServer数据库所在电脑的IP地址。但需要一些配置。

配置步骤如下:

①给带有SQLServer的电脑配置ip地址

②关闭防火墙:控制面板→防火墙

③打开SQLServer配置管理工具

打开后将图中项目,(tcp/ip和Named Pipes)设为启动状态

双击Tcp/IP配置ip地址

④在SQLServer上,设置允许远程访问:在sa上右击,选择属性

⑤设置验证方式

右击数据库实例→点击属性→点击安全

设置为SQLServer和windows认证即可

[转载]对于sa无法登陆如何用windows身份验证来修改密码

mikel阅读(902)

[转载]对于sa无法登陆,如何用windows身份验证来修改密码 – akak123 – 博客园.

一般来说 如果windows身份可以登录 还是可以重设置sa密码。

设置完后记得修改登录模式会混合登录的。

接下去需要重启msSQLservice服务。否则依旧报sa密码不对哦~ 会提示错误:

已成功与服务器建立连接,但是在登录过程中发生错误。(provider:
共享内存提成程序,error:0-管道的另一端上无任何进程。)(Microsoft SQL 
Server,错误233)

记得重启msSQLservice服务,再用改过的密码登sa

[转载]设计架构优秀的 Framework

mikel阅读(966)

[转载]设计架构优秀的 Framework – 兼谈 ORM Framework – Riceball LEE – 博客园.

本文只是自己在实际架构Framework积累的微薄的经验,如有谬误请大侠专家不吝赐教为盼。
架构设计是一种权衡和取舍。一个Framework是为了解决某一个领域内的某些问题的代码复用而因运而生的,而问题总是有多种的解决方案的。而 我们要确定唯一的架构设计的解决方案,就意味着我们要在不同的矛盾体之间做出一个取舍。我们在设计的过程总是可以看到很多的矛盾体:开放和整合,一致性和 特殊化等等。任何一对矛盾体都源于我们对Framework的不同期望,需要我们在各种方案中作出不同的取舍。没有一个Framework能够满足所有的 要求,只是架构的侧重不同。而一个设计优秀的 Framework 则是体现在其架构简单明了,层次分明,重用价值高;运行高效率,稳定(完善的TDD测试机制)。

一个架构优秀的 Framework,至少要满足以下的特征:
* 重用:为了避免重复劳动,为了降低成本,我们希望能够重用之前的代码、之前的设计。重用是 Framework 实现中最为核心的目标,重心中的重心。提高复用度是Framework的首要目标。
* 层次分明,高度部件(组件)化: 在框架中的各个部件高度独立,可拆可组(任意拆卸,任意组合),着力通用。
* 部件细化,设计精巧,运行高效,内存占用低。
* 耦合度低(可拆可组)
* 高效:不论是什么系统,我们都希望架构是高效的。
* 安全:运行安全稳定【可以通过完善TDD测试机制来保障】
* 延展:我们需要架构具有可拓展性,以适应未来可能的变化。
* 简明:一个复杂的架构不论是测试还是维护都是困难的。我们希望架构能够在满足目的的情况下尽可能的简单明了。【但是简单明了的含义究竟是什么好像并没有一 个明确的定义。例如:使用模式能够使设计变得简单,但这是建立在我熟悉设计模式的基础上。对于一个并不懂设计模式的人,他会认为这个架构很复杂。】
* 透明:把过多的实现细节隐藏起来,仅把需求的接口呈现出来(具体的实现对使用Framework的开发者来说就是透明的)。这样就提高了使用者的效率,降低了学习的门槛。

设计具体指导原则:
1、概要框架总体功能目的
2、对框架总体功能目的进行细化,分层(层次之间相对独立,互不干涉),仔细斟酌,理清层次之间的依赖关系(如,核心层,中间层,应用层)。
* 核心层:处于最低层,不依赖于Framework中的其它层;
* 中间层:根据具体 Framework 的需要自行定义,取名,注意理清层次之间的依赖关系;
* 应用层:在核心层以上,依赖于核心层;
3、从核心层开始,逐层细化各个部件,仔细推敲部件名称,构思部件的功能,合理归类。

ok,现在让我们看看 ORM Framework 的是为了解决什么问题而出现的呢?
面 向对象建模和编程经过这么多年的发展已经相当成熟,其优势在于能够适应软件开发过程中的不断变化的需求。在面向对象编程的时候很显然我们建立的对象是放在 计算机内存之中,如果关闭计算机那么我们的对象就不存在了,对象的永久性(也就是长久保存对象)是我们一直的期望。在O/R Mapping出现前我们设计程序不得不花费大量的精力和时间构建我们的Data Access Layer (DAL数据存取层),如果项目规模比较大的时候可想而知这个DAL层的复杂程度,涉及到异构数据库那就更加复杂。

在我看来,ORM Framework 的出现是为了解决两个问题:
1. 数据库无关性:平滑迁移数据库和异构数据库;
2. 实体对象的持久性:关系数据库的数据与对象的对应关系。

从这里就可以初步看出,架构至少有两个层次:
1. 数据库存取层Database Access Layer作为核心层,实现数据库无关性;
2. 实体对象映射层 ObjectMapping Layer 作为应用层实现数据到实体对象的映射,该层依赖于核心层。

数据库存取核心层是独立通用处于最底层的实现,可以直接拿出来使用的,必须保持高效和安全,主要的功能如下:
* 规范数据库操作,构造 Database 工厂模式(可拓展性),形成数据库操作包裹类 【微软的 Data Access Application Block 】
* 规范 SQL 语句,解决不同的数据库之间的 SQL 语句的差异【最简单的方式方式就是在程序中以SQL语句Id的形式调用SQL语句,将SQL语句集中于一个文件。iBatis 的 DataMapper 采用类似机制,不过它采用的是XML格式,格式的冗余数据降低了加载的效率,在保存加载机制上不够灵活,至少该让用户选择保存为不同的格式;iBatis DataMapper 另一个问题就是将 ObjectMapping 也包含其中,层次不分明,降低可复用性,】。

实体对象映射层考虑的问题就多了:
* 简单实体对象属性的映射
* Collection对象属性的映射,如实体对象购物车的物品清单就是一个Collection对象属性,收录了该购物车中的所有的物品。
* 实体对象 MetaData 的考虑,
* 业务规则,约束的考虑等等。。。

这里我就映射这个问题随便说两句,实体对象映射层是效率最低的一个层次,原因在于映射操作:将实体对象变为数据库数据,数据库数据变为实体对象,而正是这个映射操作使得运行速度大大降低,内存占用大大的增加。
如 果将所有的实体数据不分青红皂白全部对象化,那么即使是采用Cache(是以牺牲内存为代价的)和分页机制(一次不要取个万把千条数据的,客户也看不过 来,一次百来条数据就差不多了,这样就减少了内存的占用和映射操作的时间),但是,当系统面临逐渐增加的并发访问数量面前,系统的性能恶化相当厉害。我不 知道大家说的什么才算是大型系统,企业级应用,也许是特指那些愿意花高价购买IBM RS/6000之流的机器的冤大头们吧。但是对于我们这些搞技术的,则是该将注意力集中在如何充分挖掘机器的每一分潜力上才是,我相信对于每一个量入为出 的企业来说,它应该是欣赏的。
这个目前,我也没有想到什么好的办法,对于减少内存开销,有个建议就是在设计时候,尽可能的延迟加载时间(如实体对 象购物车的物品清单,实际数据的加载只有当访问该属性的时候才加载,而对于大的备注,Blob类型的属性也可以采取类似的机制)。实际上,大多数用户的操 作都是在浏览,因此对于浏览数据的形式,可以绕过ObjectMapping层,通过数据库存取层返回dataset直接操作,这样也能进一步提高速度和 降低内存的消耗。

[转载]C#性能优化实践

mikel阅读(1114)

[转载]C#性能优化实践 – 葡萄城控件技术团队博客 – 博客园.

性能是考量一个软件产品好坏的重要指标,与产品的功能有着同等重要的地位。用户在选择一款软件产品的时候基本都会亲身试验比较同类产品的性能。作为选购那个软件重要因素之一。

 

软件的性能指什么

 

  1. 降低内存消耗
    在软件开发中,内存消耗一般作为次要的考虑,因为现在的计算机一般都拥有比较大的内存,很多情况下,性能优化的手段就是空 间换取时间。但是,并不是说,我们可以肆无忌惮的挥霍内存。如果需要支持在大数据量的用例时,如果内存被耗尽,操作系统会发生频繁的内外存交换。导致执行 速度急剧下降。
  2. 提升执行速度
    1. 加载速度。
    2. 特定操作的响应速度。包括,点击,键盘输入,滚动,排序过滤等。

 

性能优化的原则

 

  1. 理解需求
    以MultiRow产品为例,MultiRow的一个性能需求是:”百万行数据绑定下平滑滚动。”整个MultiRow项目的开发过程一直要考虑这个目标。
  2. 理解瓶颈
    根据经验,99%的性能消耗是由于1%的代码造成的。所以,大部分性能优化都是针对这1%的瓶颈代码进行的。具体实施也就分为两步。首先,确定瓶颈,其次消除瓶颈。
  3. 切忌过度
    首先必须要认识到,性能优化本身是有成本的。这个成本不单单体现在做性能优化所付出的工作量。还包括为性能优化而写 出的复杂代码,额外的维护成本,会引入新的Bug,额外的内存开销等。 一个常见问题是,一些刚接触软件开发的同学会对一些不必要的点生搬硬套性能优化技巧或者设计模式,带来不必要的复杂度。性能优化常常需要对收益和成本之间 做出权衡。

 

如何发现性能瓶颈

 

上一节提到,性能优化的第一步就是发现性能瓶颈,这一节主要介绍定位性能瓶颈的一些实践。

如何获取内存消耗
以下代码可以获取某个操作的内存消耗。

// 在这里写一些可能消耗内存的代码,例如,如果想了解创建一个GcMultiRow软件需要多少内存可以执行以下代码

long start = GC.GetTotalMemory(true);

var gcMulitRow1 = new GcMultiRow();

GC.Collect();

// 确保所有内存都被GC回收

GC.WaitForFullGCComplete();

long end = GC.GetTotalMemory(true);

long useMemory = end - start;

如何获取时间消耗
以下代码可以获取某个操作时间消耗。

System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
for (int i = 0; i < 1000; i++)
{
gcMultiRow1.Sort();
}
watch.Stop();
var useTime = (double)watch.ElapsedMilliseconds / 1000;
  1. 这里把一个操作循环执行了1000次,最后再把消耗的时间除以1000来确定最终消耗的时间。可以是结果更准确稳定,排除意外数据。
  2. 通过CodeReview发现性能问题。
    很多情况下,可以通过CodeReview发现性能问题。对于大数据量的循环,要格外关注。循环内的逻辑应该执行的尽可能的快。
  3. ANTS Performance Profiler
    ANTS Profiler是款功能强大的性能检测软件。可以很好的帮助我们发现性能瓶颈。使用这款软件定位性能瓶颈可以起到事半功倍的 效果。熟练使用这个工具,我们可以快速准确的定位到有性能问题的代码。 这个工具很强大,但是也并不是完美无缺的。首先,这是一款收费软件,部门只有几个许可号。其次,这个软件的工作原理是在IL中加入一些钩子,用来记录时 间。所以在分析时,软件的执行速度会比实际运行慢一些获得的数据也因此并不是百分之百的准确,应该把软件分析的数据作为参考,帮助快速定位问题,但是不要 完全依赖,还要结合其他技巧来分析程序的性能。

性能优化的方法和技巧

定位了性能问题后,解决的办法有很多。这个章节会介绍一些性能优化的技巧和实践。

    1. 优化程序结构
      对于程序结构,在设计时就应该考虑,评估是否可以达到性能需求。如果后期发现了性能问题需要考虑调整结构会带来非常大的开销。举例:

      1. GcMultiRowGcMultiRow要支持100万行数据,假设每行有10列的话,就需要有1000万个单元格,每个单元格上又有很多的属 性。如果不做任何优化的话,大数据量时,一个GcMultiRow软件的内存开销会相当的大。GcMultiRow采用的方案是使用哈希表来存储行数据。 只有用户改过的行放到哈希表里,而对于大部分没有改过的行都直接使用模板代替。就达到了节省内存的目的。
      2. Spread for WPF/Silverlight (SSL)WPF的画法和Winform不同,是通过组合View元素的方法实现的。SSL同样支持百万级的数据量,但是又不能给每个单元格都分配一个 View。所以SSL使用了VirtualizePanel来实现画法。思路是每一个View是一个Cell的展示模块。可以和Cell的数据模块分离。 这样。只需要为显示出来的Cell创建View。当发生滚动时会有一部分Cell滚出屏幕,有一部分Cell滚入屏幕。这时,让滚出屏幕的Cell和 View分离。然后再复用这部分View给新进入屏幕的Cell。如此循环。这样只需要几百个View就可以支持很多的Cell。
    2. 缓存
      缓存(Cache)是性能优化中最常用的优化手段.适用的情况是频繁的获取一些数据,而每次获取这些数据需要的时间比较长。这时,第一次 获取的时候会用正常的方法,并且在获取之后把数据缓存下来。之后就使用缓存的数据。 如果使用了缓存的优化方法,需要特别注意缓存数据的同步,就是说,如果真实的数据发生了变化,应该及时的清除缓存数据,确保不会因为缓存而使用了错误的数 据。 举例:

      1. 使用缓存的情况比较多。最简单的情况就是缓存到一个Field或临时变量里。
for(int i = 0; i < gcMultiRow.RowCount; i++)
{
// Do something;
}

以上代码一般情况下是没有问题的,但是,如果GcMultiRow的行数比较大。而RowCount属性的取值又比较慢的时候就需要使用缓存来做性能优化。

int rowCount = gcMultiRow.RowCount;
for (int i = 0; i < rowCount; i++)
{
// Do something;
}

使用对象池也是一个常见的缓存方案,比使用Field或临时变量稍微复杂一点。 例如,在MultiRow中,画边线,画背景,需要用到大量的Brush和Pen。这些GDI对象每次用之前要创建,用完后要销毁。创建和销毁的过程是比 较慢的。GcMultiRow使用的方案是创建一个GDIPool。本质上是一些Dictionary,使用颜色做Key。所以只有第一次取的时候需要创 建,以后就直接使用以前创建好的。以下是GDIPool的代码:

public static class GDIPool
{
Dictionary _cacheBrush = new Dictionary();
Dictionary _cachePen = new Dictionary();
public static Pen GetPen(Color color)
{
Pen pen;
if_cachePen.TryGetValue(color, out pen))
{
return pen;
}
pen = new Pen(color);
_cachePen.Add(color, pen);
return pen;
}
}

懒构造
有时候,有的对象创建需要花费较长时间。而这个对象可能并不是所有的场景下都需要使用。这时,使用赖构造的方法可以有效提高性能。 举例:对象A需要内部创建对象B。对象B的构造时间比较长。 一般做法:

public class A
{
public B _b = new B();
}

一般做法下由于构造对象A的同时要构造对象B导致了A的构造速度也变慢了。优化做法:

public class A
{
private B _b;
public B BProperty
{
get
{
if(_b == null)
{
_b = new B();
}
return _b;
}
}
}
  1. 优化后,构造A的时候就不需要创建B对象,只有需要使用的时候才需要构造B对象。
  2. 优化算法
    优化算法可以有效的提高特定操作的性能,使用一种算法时应该了解算法的适用情况,最好情况和最坏情况。 以GcMultiRow为例,最初MultiRow的排序算法使用了经典的快速排序算法。这看起来是没有问题的,但是,对于表格软件,用户经常的操作是对 有序表进行排序,如顺序和倒序之间切换。而经典的快速排序算法的最差情况就是基本有序的情况。所以经典快速排序算法不适合MultiRow。最后通过改的 排序算法解决了这个问题。改进的快速排序算法使用了3个中点来代替经典快排的一个中点的算法。每次交换都是从3个中点中选择一个。这样,乱序和基本有序的 情况都不是这个算法的最坏情况,从而优化了性能。
  3. 了解Framework提供的数据结构
    我们现在工作的.net framework平台,有很多现成的数据数据结构。我们应该了解这些数据结构,提升我们程序的性能: 举例:

      1. string 的加运算符 VS StringBuilder: 字符串的操作是我们经常遇到的基本操作之一。 我们经常会写这样的代码 string str = str1 + str2。当操作的字符串很少的时候,这样的操作没有问题。但是如果大量操作的时候(例如文本文件的Save/Load, ASP.NET的Render),这样做就会带来严重的性能问题。这时,我们就应该用StringBuilder来代替string的加操作。
      2. Dictionary VS List Dictionary和List是最常用的两种集合类。选择正确的集合类可以很大的提升程序的性能。为了做出正确的选择,我们应该对Dictionary 和List的各种操作的性能比较了解。 下表中粗略的列出了两种数据结构的性能比较。
        操作 List Dictionary
        索引
        Find(Contains)
        Add
        Insert
        Remove
      3. TryGetValue 对于Dictionary的取值,比较直接的方法是如下代码:
    if(_dic.ContainKey("Key")
    {
    return _dic\["Key"\];
    }
    

    当需要大量取值的时候,这样的取法会带来性能问题。优化方法如下:

    object value;
    if(_dic.TryGetValue("Key", out value))
    {
    return value;
    }
    
  4. 使用TryGetValue可以比先Contain再取值提高一倍的性能。
  5. 为Dictionary选择合适的Key。 Dictionary的取值性能很大情况下取决于做Key的对象的Equals和GetHashCode两个方法的性能。如果可以的话使用Int做Key 性能最好。如果是一个自定义的Class做Key的话,最好保证以下两点:1. 不同对象的GetHashCode重复率低。2. GetHashCode和Equals方法立即简单,效率高。
  6. List的Sort和BinarySearch性能很好,如果能满足功能需求的话推荐直接使用,而不是自己重写。
    List<int> list = new List<int>{3, 10, 15};
    list.BinarySearch(10); // 对于存在的值,结果是1
    list.BinarySearch(8); // 对于不存在的值,会使用负数表示位置,如查找8时,结果是-2, 查找0结果是-1,查找100结果是-4.

通过异步提升响应时间多线程
有些操作确实需要花费比较长的时间,如果用户的操作在这段时间卡死会带来很差的用户体验。有时候,使用多线程技术可以解决这个问 题 举例: CalculatorEngine在构造的时候要初始化所有的Function。由于Function比较多,初始化时间会比较长。这是就用到了多线程技 术,在工作线程中做Function的初始化工作,就不影响主线程快速响应用户的其他操作了。代码如下:

public CalcParser()
{
if (_functions == null)
{
lock (_obtainFunctionLocker)
{
if (_functions == null)
{
System.Threading.ThreadPool.QueueUserWorkItem((s) =&gt;
{
if (_functions == null)
{
lock (_obtainFunctionLocker)
{
if (_functions == null)
{
_functions = EnsureFunctions();
}
}
}
});
}
}
}
}
    1. 这里比较慢的操作就是EnsureFunctions函数,是在另一个线程里执行的,不会影响主线程的响应。当然,使用多线程是一个比较有难度的方案,需要充分考虑跨线程访问和死锁的问题。
    2. 加延迟时间
      在GcMultiRow实现AutoFilter功能的时候使用了一个类似于延迟执行的方案来提升响应速度。 AutoFilter的功能是用户在输入的过程中根据用户的输入更新筛选的结果。数据量大的时候一次筛选需要较长时间,会影响用户的连续输入。使用多线可 能是个好的方案,但是使用多线程会增加程序的复杂度。MultiRow的解决方案是当接收到用户的键盘输入消息的时候,并不立即出发Filter,而是等 待0.3秒。如果用户在连续输入,会在这0.3秒内再次收到键盘消息,就再等0.3秒。直到连续0.3秒内没有新的键盘消息时再触发Filter。保证了 快速响应用户输入的目的。
    3. Application.Idle事件
      在GcMultiRow的Designer里,经常要根据当前的状态刷新ToolBar上按钮的 Disable/Enable状态。一次刷新需要较长的时间。如果用户连续输入会有卡顿的感觉,影响用户体验。GcMultiRow的优化方案是挂系统的 Application.Idle事件。当系统空闲的时候,系统会触发这个事件。接到这个事件表示此时用户已经完成了连续的输入,这时就可以从容的刷新按 钮的状态了。
    4. Invalidate, BeginInvoke. PostEvent 平台本身也提供了一些异步方案。
      例如;在Winform下,触发一块区域重画的时候,一般不适用Refresh而是Invalidate,这样会触发异步的刷新。在触发之前可以多次Invalidate。BeginInvoke,PostMessage也都可以触发异步的行为。
  1. 了解平台特性
    如WPF的DP DP相对于CLR property来说是很慢的,包括Get和Set都很慢,这和一般质感上Get比较快Set比较慢不一样。如果一个DP需要被多次读取的话建议是CLR property做Cache。
  2. 进度条,提升用户体验
    有时候,以上提到的方案都没有办法快速响应用户操作,进度条,一直转圈圈的图片,提示性文字如”你的操作可能需要较长时间请耐心等待”。都可以提升用户体验。可以作为最后方案来考虑

[转载]写一个简单高效的 JSON 查询器

mikel阅读(954)

[转载]写一个简单高效的 JSON 查询器 – EtherDream – 博客园.

JSON可谓是JavaScript的亮点,它能用优雅简练的代码实现Object和Array的初始化。同样是基于文本的数据定义,它比符号分隔更有语义,比XML更简洁。因此越来越多的JS开发中,使用它作为数据的传输和储存。

JS数组内置了不少有用的方法,方便我们对数据的查询和筛选。例如我们有一堆数据:

var heros = [
// 名============攻=====防=======力量====敏捷=====智力====
{name:'冰室女巫', DP:38, AP:1.3, Str:16, Dex:16, Int:21},
{name:'沉默术士', DP:39, AP:1.1, Str:17, Dex:16, Int:21},
{name:'娜迦海妖', DP:51, AP:6.0, Str:21, Dex:21, Int:18},
{name:'赏金猎人', DP:39, AP:4.0, Str:17, Dex:21, Int:16},
{name:'剧毒术士', DP:45, AP:3.1, Str:18, Dex:22, Int:15},
{name:'光之守卫', DP:38, AP:1.1, Str:16, Dex:15, Int:22},
{name:'炼金术士', DP:49, AP:0.6, Str:25, Dex:11, Int:25}
//...
];

要查询攻击大于40并且防御小于4的英雄,我们可以用Array的filter方法:

var match = heros.filter(function(e) {
return e.DP > 40 && e.AP < 4; });

返回得到一个数组,包括符合条件的2个结果。

相比手工去写循环判断,filter方法为我们提供了很大的方便。但它是基于函数回调的,所以每次使用必须写一个function,对于简单的查询很是累赘,而且使用回调效率也大大降低。但这是也没有办法的,想简单必然要牺牲一定性能。 如果能使用比这更简单的语句,并且完全拥有代码展开时效率,该有是多么完美的事。

先来想象下,要是能将上面的代码写成这样(Demo在文章最后):

var match = heros.select(‘@DP>40 AND @AP<4’);

看上去有点像SQL,连语法都换了?这样岂不是要写一个词法分析,语义解释等等等等一大堆的脚本引擎的功能了,没个几千上万行代码都搞不定,而 且效率肯定更糟了。。。如果想到那么复杂,那么你还没深刻的理解脚本的精髓。但凡是脚本语言,都有运行时动态解释代码的接口,例如vbs的 execute();js的eval(),new Function(),甚至创建一个<script>动态写入代码。

显然,要是能将另一种语言,翻译成js代码,那么就可直接交给宿主来执行了!

例如上面select中的字符,我们简单的将”@”替换成”e.”, “AND”替换成”&&”,于是就成了一个合法的js表达式,完全可以交给eval来执行。

所以我们要做的,就是将原始语句翻译成js语句来执行。并且为了提高效率,将翻译好的js表达式内联到一个上下文环境,生成一个可执行的函数体,而不是每次遍历中都依靠回调来判断。

于是,函数模版就要派上用场了。

 

 

 

函数模版简介

在C++里面,有宏和类模版这么个东西,可以让一些计算在编译阶段就完成了,大幅提升了运行时代码的性能。脚本虽然没有严格意义上的编译,但在 第一次执行的时候会解析并充分的优化,这是目前主流浏览器相互竞争点。所以,我们要将重复eval的代码,镶嵌到事先提供的样板函数里:一个准备就绪,就 差表达式计算的函数。

/**
* 模版: tmplCount
* 功能: 统计arr数组中符合$express表达式的数量
*/
function tmplCount(arr) {
var count = 0;

for(var i = 0; i &lt; arr.length; i++) {
var e = arr[i];

if($express) {
count++;
}
}
return count;
}

上面就是一个模板函数,用来统计参数arr[]中符合$express条件的数量。除了if(…)内的表达式外,其他都已经准备就绪了。字符”$express”也可以换成其他标识,只要不和函数内其他字符冲突即可。

当我们需要实例化时,首先通过tmplCount.toString()将函数转成字符串格式,然后将其中的”$express”替换成我们想要的表达式,最后eval这串代码字符,一个模板函数的实例就产生了!

我们简单的演示下:

/**
* 函数: createInstance
* 参数: exp
* 一段js表达式字符串,用来替换tmplCount模板的$express
* 返回:
* 返回一个Function,模版tmplCount的实例
*/
function createInstance(exp)
{
// 替换模板内的表达式
var code = tmplCount.toString()
.replace('$express', exp);

// 防止匿名函数直接eval报错
var fn = eval('0,' + code);

// 返回模板实例
return fn;
}

// 测试参数
var student = [
{name: 'Jane', age: 14},
{name: 'Jack', age: 20},
{name: 'Adam', age: 18}
];

// demo1
var f1 = createInstance('e.age=14');
alert(f2(student)); //2个

其中的f1,f2就是tmplCount模板的两个实例。最终我们调用的实例函数中,已经包含了经过解析并且优化了的表达式语句,就像我们事先写了两个同样功能的函数一样。由于判断的表达式已经完全融合在函数内了,所以不用在遍历的时候回调,效率大幅提升。

其实说白了,tmplCount的存在仅仅是为了提供这个函数的字符串而已,其本身从来不会被调用。事实上用字符串的形式定义也一样,只不过用函数书写比较直观,方便测试。

值得注意的是,如果脚本后期需要压缩优化,那么tmplCount模板绝对不能参与,否则对应的”e.”和”$express”都有可能发生变化。

JSON基本查询功能

函数模板的用处和实现介绍完了,再来回头看之前的JSON查询语言。我们只需将类似SQL的语句,翻译成js表达式,并且生成一个函数模板实例。对于相同的语句,我们可以进行缓存,避免每次都翻译。

首先我们实现查询器的模板:

var __proto = Object.prototype;

//
// 模板: __tmpl
// 参数: $C
// 说明: 记录并返回_list对象中匹配$C的元素集合
//
var __tmpl = function(_list) {
var _ret = [];
var _i = -1;

for(var _k in _list) {
var _e = _list[_k];

if(_e != __proto[_k]) {
if($C)
_ret[++_i] = _e;
}
}
return _ret;

}.toString();

然后开始写Object的select方法:

//
// select方法实现
//
var __cache = {};

__proto.select = function(exp) {
if(!exp)
return [];

var fn = __cache[exp];

try {
if(!fn) {
var code = __interpret(exp); //解释表达式
code = __tmpl.replace('$C', code); //应用到模版

fn = __cache[exp] = __compile(code); //实例化函数
}

return fn(this); //查询当前对象
}
catch(e) {
return [];
}
}

其中__cache表实现了查询语句的缓存。对于重复的查询,性能可以极大的提升。

    function __compile() { return eval('0,' + arguments[0]); }

__compile之所以单独写在一个空函数里,就是为了eval的时候有个尽可能干净的上下文环境。

__interpret是整个系统的重中之重,负责将查询语句翻译成js语句。它的实现见智见仁,但尽可能简单,不要过度分析语法。

具体代码查看: http://files.cnblogs.com/index-html/jsonselect.js
出于演示,目前只实现部分基本功能。以后还可以加上 LIKE,BETWEEN,ORDER BY 等等常用的功能。

Demo

var heros = [
// 名============攻=====防=======力量====敏捷=====智力====
{name:'冰室女巫', DP:38, AP:1.3, Str:16, Dex:16, Int:21},
{name:'沉默术士', DP:39, AP:1.1, Str:17, Dex:16, Int:21},
{name:'娜迦海妖', DP:51, AP:6.0, Str:21, Dex:21, Int:18},
{name:'赏金猎人', DP:39, AP:4.0, Str:17, Dex:21, Int:16},
{name:'剧毒术士', DP:45, AP:3.1, Str:18, Dex:22, Int:15},
{name:'光之守卫', DP:38, AP:1.1, Str:16, Dex:15, Int:22},
{name:'炼金术士', DP:49, AP:0.6, Str:25, Dex:11, Int:25}
//...
];
// 查询:力量,敏捷 都超过20的
    // 结果:娜迦海妖
    var match = heros.select('@Str>20 AND @Dex>20');

    // 查询:“士”结尾的
    // 结果:沉默术士,剧毒术士,炼金术士
    var match = heros.select('right(@name,1)="士" ');

    // 查询:生命值 超过500的
    // 结果:炼金术士
    var match = heros.select('100 + @Str*19 > 500');

 

[原创]SQL根据日期和流水号生成订单号

mikel阅读(1550)

现在需要导入一批数据入库,需要生成订单号,格式如下:

201207170001

目前表结构如下:

Id   date                 ordercode

1   2012-07-12

于是编写SQL进行生成订单号,代码如下:

select CONVERT(nvarchar,日期,112)+Right(RTRIM('0000'+CAST(id as CHAR(4))),4)
from oa_ruku
update oa_ruku
set
ordercode=CONVERT(nvarchar,日期,112)+Right(RTRIM(ordercode),4)

[转载]dnspod-sr - DNS 服务器 - 开源中国

mikel阅读(1091)

[转载]dnspod-sr – DNS 服务器 – 开源中国.

DNSPod Security Recursive DNS Server

关于

dnspod-sr 是一个运行在 Linux 平台上的高性能的递归 DNS 服务器软件,具备高性能、高负载、易扩展的优势,非 BIND 等软件可以比拟。

特性

  1. 高性能,比所有流行的开源 DNS 软件性能高出2倍以上
  2. 安全,能抵御一般攻击
  3. 稳定性,有效降低解析失败率
  4. 主动刷新缓存,响应速度更快
  5. 易于扩展,非常容易部署
  6. 防污染,能够正确解析被污染域名

性能

dnspod-sr 依托于 DNSPod 多年运营和优化 DNS 服务的经验,针对国内复杂的网络情况,对递归 DNS 进行了一系列的优化,比较其他开源软件,性能得到大幅提升。

测试环境

千兆网卡,4核 CPU,4G 内存,Linux 64位系统。

性能测试

  • dnspod-sr: 15万 qps
  • BIND 9.9: 7万 qps
  • unbound 4.7: 8万 qps

Benchmark

解决方案

  1. 架设 dnspod-sr 集群,替换各大运营商目前基于 BIND 的陈旧方案,减少运营成本
  2. 公司、学校、政府等组织内部 DNS,解析外部不可见的私有域名,提高上网速度

快速开始

下载源码:

git clone https://github.com/DNSPod/dnspod-sr.git cd dnspod-sr 

或者下载压缩包:

https://github.com/DNSPod/dnspod-sr/zipball/master 

编译源码:

make 

运行

./dnspod-sr 

Roadmap

  • 支持集群式部署

[转载]无广告看视频方法

mikel阅读(862)

[转载]【趣】无广告看视频 – weifield – 博客园.

众所周知,广告是视频网站的一项重要盈利方式。而随着优酷和土豆的合并,显示广告的时间也越来越长。其霸气外漏,使得用户很不爽。

无意间看到网上有关于让广告消失的操作。

目的:

无广告看视频。

原理:

每次打开视频网页,此视频网站就会主动请求显示广告的连接。假如我们让此链接失效,则达到无广告的效果。那如何才能失效呢?

修改hosts文件了。让host文件中的网址和指向本地的环回地址127.0.0.1这样就可以了。

关于hosts文件:

hosts文件可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要 登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统再会将网址提交DNS域名 解析服务器进行IP地址的解析。

Hosts文件位置:

C:\WINDOWS\system32\drivers\etc 中

具体操作:

下面列出了视频 广告 地址 大全,只要打开hosts文件,将如下内容复制粘贴,追加到hosts文件中即可。

#优酷
.0.0.1 atm.youku.com
.0.0.1 Fvid.atm.youku.com
.0.0.1 html.atm.youku.com
.0.0.1 valb.atm.youku.com
.0.0.1 valf.atm.youku.com
.0.0.1 valo.atm.youku.com
.0.0.1 valp.atm.youku.com
.0.0.1 lstat.youku.com
.0.0.1 speed.lstat.youku.com
.0.0.1 urchin.lstat.youku.com
.0.0.1 stat.youku.com
.0.0.1 static.lstat.youku.com
.0.0.1 valc.atm.youku.com
.0.0.1 vid.atm.youku.com
.0.0.1 walp.atm.youku.com
#百度:
.0.0.1 a.baidu.com
.0.0.1 baidutv.baidu.com
.0.0.1 bar.baidu.com
.0.0.1 c.baidu.com
.0.0.1 cjhq.baidu.com
.0.0.1 cpro.baidu.com
.0.0.1 drmcmm.baidu.com
.0.0.1 e.baidu.com
.0.0.1 eiv.baidu.com
.0.0.1 hc.baidu.com
.0.0.1 hm.baidu.com
.0.0.1 ma.baidu.com
.0.0.1 nsclick.baidu.com
.0.0.1 spcode.baidu.com
.0.0.1 tk.baidu.com
.0.0.1 union.baidu.com
.0.0.1 ucstat.baidu.com
.0.0.1 utility.baidu.com
.0.0.1 utk.baidu.com
.0.0.1 focusbaiduafp.allyes.com
#奇艺
.0.0.1 afp.qiyi.com
.0.0.1 focusbaiduafp.allyes.com
#CNTV
.0.0.1 a.cctv.com
.0.0.1 a.cntv.cn
.0.0.1 ad.cctv.com
.0.0.1 d.cntv.cn
.0.0.1 adguanggao.eee114.com
.0.0.1 cctv.adsunion.com
#新浪视频
.0.0.1 dcads.sina.com.cn
#pptv
.0.0.1 pp2.pptv.com
#乐视
.0.0.1 pro.letv.com
#搜狐高清
.0.0.1 images.sohu.com
@HostsX 国内站点广告/视频类网站
#CNTV
.0.0.1 a.cctv.com
.0.0.1 a.cntv.cn
.0.0.1 ad.cctv.com
.0.0.1 d.cntv.cn
.0.0.1 adguanggao.eee114.com
.0.0.1 cctv.adsunion.com
#我乐网
.0.0.1 acs.56.com
.0.0.1 acs.agent.56.com
.0.0.1 acs.agent.v-56.com
.0.0.1 bill.agent.56.com
.0.0.1 bill.agent.v-56.com
.0.0.1 stat.56.com
.0.0.1 stat2.corp.56.com
.0.0.1 union.56.com
.0.0.1 uvimage.56.com
.0.0.1 v16.56.com
#6间房
.0.0.1 pole.6rooms.com
.0.0.1 shrek.6.cn
.0.0.1 simba.6.cn
.0.0.1 union.6.cn
#土豆网
.0.0.1 adextensioncontrol.tudou.com
.0.0.1 iwstat.tudou.com
.0.0.1 nstat.tudou.com
.0.0.1 stats.tudou.com
.0.0.1 *.p2v.tudou.com*
.0.0.1 at-img1.tdimg.com
.0.0.1 at-img2.tdimg.com
.0.0.1 at-img3.tdimg.com
.0.0.1 adplay.tudou.com
.0.0.1 adcontrol.tudou.com
.0.0.1 stat.tudou.com
#酷6网
.0.0.1 1.allyes.com.cn
.0.0.1 analytics.ku6.com
.0.0.1 gug.ku6cdn.com
.0.0.1 ku6.allyes.com
.0.0.1 ku6afp.allyes.com
.0.0.1 pq.stat.ku6.com
.0.0.1 st.vq.ku6.cn
.0.0.1 stat0.888.ku6.com
.0.0.1 stat1.888.ku6.com
.0.0.1 stat2.888.ku6.com
.0.0.1 stat3.888.ku6.com
.0.0.1 static.ku6.com
.0.0.1 v0.stat.ku6.com
.0.0.1 v1.stat.ku6.com
.0.0.1 v2.stat.ku6.com
.0.0.1 v3.stat.ku6.com
#激动网
.0.0.1 86file.megajoy.com
.0.0.1 86get.joy.cn
.0.0.1 86log.joy.cn
#天线视频
.0.0.1 casting.openv.com
.0.0.1 m.openv.tv
.0.0.1 uniclick.openv.com
#迅雷看看屏蔽:
.0.0.1 mcfg.sandai.net
.0.0.1 biz5.sandai.net
.0.0.1 server1.adpolestar.net
.0.0.1 advstat.xunlei.com
.0.0.1 mpv.sandai.net

不良后果:

有时候会显示,无法打开广告页…然后还是继续等待。这时,你就打开hosts文件,剪切上面的代码,保存,刷新页面,就搞定了。然后再打开hosts,把代码粘贴进去。
感慨:

收集链接的人好屌….

试一试,成功了吗?
扩展:

当然,原理有了,也可以根据原理来写一个winform程序,来执行这些操作。

具体操作:

将无扩展名的hosts文件看成文本文件,对文本文件的读取、写入操作。

[转载]权限管理设计

mikel阅读(1122)

[转载]权限管理 – 一点一线 – 博客园.

  1. 数据库表设计:

  1. 后台的登录时序图:

  1. 详细讲解设计:假定,用户(op)为zhangsan ,id是1,角色是:200. 那么以下的情况:

    a) 权限文件

      i.当 添加/修改 用户权限时,会修改对应权限文件,该文件以用户id(op_id)为名 1.php,存放在指定的权限文件夹下

      ii.删除用户时,会把对应的权限文件删除

      iii.验证权限时,会把该权限文件引入,在根据当前访问连接地址,比 如:http://www.xxx.com/user/op.php?act=del ,会获取/user/op.php这部分的page_url,来获取menu表中与之对应的id,而act=del则表示他的权限,【根据权限文件中存放 的是:menu_id=>权限】这样的格式,就可以对比出,用户是否有权限访问。当然,如果权限文件中连这个menu_id都没有的话,肯定是没有 权限的。

    b)菜单文件

      i.跟权限文件一样,也是在用户添加权限后,就会把它对应的权限的菜单,生成一个以id为名的html文件.(1.html)

      ii.用户删除后,对应的1.html文件删除.

      iii.登录成功后,后台的右侧菜单,就导入该文件,渲染一下即可。

      iv.菜单分为:固定菜单[配置文件,针对角色高的用户拥有] 和 可分配的菜单[存放在数据库],不同的角色,菜单不一样,如果是普通的角色,那么肯定没有固定菜单的权限。

    c)操作员角色(op_role) 包括:1 = 操作员,200 = 运维操作员,254 = 超级管理员,255 = 系统管理员

      i.这里所用到的角色不是用来控制权限。而只是控制后台的菜单,假如用户(op) A角色是255,那么会有在判断用户权限时,就会显示出该角色对应的固定菜单,比如:用户的管理,菜单的管理,不会因为删除了所有菜单而导致无法使用的情况!

    d)验证流程:

       i.  菜单载入流程

      ii.  权限的判断:

    权限的运算:http://www.cnblogs.com/toby/archive/2011/10/23/2221863.html

[转载]基于位运算的权限控制

mikel阅读(1198)

[转载]基于位运算的权限控制 | 将之典藏.

原理

在Linux文件系统中,一个用户对文件或目录所拥有的权限分为三种:”可读”、”可写”和”可执行”,分别用 1 、2 和 4 来表示,它们之间可以任意组合:有“可读”、“可写”权限就用 3 来表示(1 + 2 = 3);有”可读“、”可执行“权限就用5来表示(1 + 4 = 5),三种权限全部拥有就用 7 表示(1 + 2 + 4 = 7)。

实际上,这种运算是基于二进制的。

假设可执行、可写、可读三种权限分别对应三个状态位,如果用户具有某种权限,那么将对应的状态位标识为“1”,反之则标识为“0”。如图:

位运算与权限控制

如果只有“可读”权限,那么就对应二进制数:001,将这个二进制数转成十进制就得到1;如果同时具有“可读”、“可写”权限,二进制数则对应为: 011,转十进制得:3;同理,三种权限都有的,十进制就等于7。

实现

在PHP中,通过位运算符很容易就可以做到类似的权限控制:

<!--?php <br ?--> //定义权限
define('READ', 1&lt;&lt; 0); // 把可读权限放在最右边
define('WRITE', 1&lt; define('EXCUTE', 1&lt;

PHP语言本身的错误控制 也是用位运算来做的,它甚至还利用了按位异或按位非,使得错误控制更加精确。

优点和缺陷

位运算的运算对象是二进制的位,速度快,效率高,而且节省存储空间,位运算做权限控制又相当地灵活。但是,位运算也有很大的局限,因为在32位计算机上,位移不能超过32次,这就要求权限数量不超过32种。


延伸阅读:

  • MySQLSET类型,也是基于位运算的,恰当的运用,效果不错,可以参看教程

作者:肖斌
本文链接:http://xiaobin.net/200906/bitwise-permission/