v8里一段很巧妙的带cache的字符类型判断模板类

编译过程经常需要判断字符的类型。

 

有些判断很简单,数字就是['0','9'],字幕就是['a','z']和['A','Z']。几个比较语句就搞定了。

 

有些比需要比较多的判断次数,因为他们是一个不连续的编码的字符集合。像最常见的空字符集合,{' ', '/t' ... }。

遇到这种集合就只能逐个比较。可以通过对集合排序,减少比较次数,但是比较的平均次数仍然和这个集合的大小成正比。(假设每个字符出现的概率一样)。

 

如果能引入一个方法,把比较次数缩小成1,那么整个扫描速度就可以提高。

 

v8引擎里有一个模板类,专门处理这个问题。

这个类通过cache,把比较次数缩小到1。而且把判断逻辑和cache的逻辑分离。可以适用任何字符集合判断。

 

template <class T, int size = 256>
class Predicate {
 public:
  inline Predicate() { }
  inline bool get(uchar c);
 private:
  friend class Test;
  bool CalculateValue(uchar c);
  struct CacheEntry {
    inline CacheEntry() : code_point_(0), value_(0) { }
    inline CacheEntry(uchar code_point, bool value)
      : code_point_(code_point),
        value_(value) { }
    uchar code_point_ : 21;
    bool value_ : 1;
  };
  static const int kSize = size;
  static const int kMask = kSize - 1;
  CacheEntry entries_[kSize];
};

 

模板参数T是实现判断逻辑的类。size是cache大小,这个数字一定要是2的幂,默认值其实足够好了。

 

这个Predicte的工作方式很简单,先找找cache里有这个字符吗,有则返回cache,没有,判断一下,记录新的结果,记录到cache里。

 

template <class T, int s> bool Predicate<T, s>::get(uchar code_point) {
  CacheEntry entry = entries_[code_point & kMask];
  if (entry.code_point_ == code_point) return entry.value_;
  return CalculateValue(code_point);
}

template <class T, int s> bool Predicate<T, s>::CalculateValue(
    uchar code_point) {
  bool result = T::Is(code_point);
  entries_[code_point & kMask] = CacheEntry(code_point, result);
  return result;
}

 

这里可以看出cache的分配是通过掩码进行的,实际上就是看这个多字节字符(uchar是int)的最后几位来 分配。掩码kMask是根据模板参数求得。如果size是256那掩码就是求最后一个字节。CacheEntry保存了最后一次比较信息。可以检查出冲突 (两个字符占用同一个cache),以最后一次比较优先记录。T类提供静态成员方法Is来判断字符是否属于这个集合。

 

整个方法可以看作是一个hash表开放地址发的变形。希望通过一次散列查找,替代集合运算。如果这个集合判断十分简单,比如数字,反而没必要这么做了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值