作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


做 profile 发现 url.QueryEscape 占用的 CPU 时间较多,于是搜索到了一个资料:net/url: optimize unescape and escape.

于是在这个代码的基础上改了FastQueryString的版本。

在 Macbook pro m2 上测试:

  • url.QueryEscape() 281.5 ns/op
  • FastQueryEscape() 38.40 ns/op, 快7.33 倍

具体代码如下:query_escape.go

package stringsutil

import (
"bytes"
"reflect"
"unsafe"
) func shouldPathEscape(c byte) bool {
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
return false
}
switch c {
case '-', '_', '.', '~': // = & ':', '@', '+', '$'
return false
}
return true
} var (
shouldEscapeLUT [256]bool
) func init() {
for i := 0; i < 256; i++ {
shouldEscapeLUT[i] = shouldPathEscape(byte(i))
}
} // FastQueryEscape fast version
func FastQueryEscape(s string, buf *bytes.Buffer) []byte {
hexCount := 0
for i := 0; i < len(s); i++ {
if shouldEscapeLUT[s[i]] {
hexCount++
}
}
if hexCount == 0 {
return NoAllocBytes(s)
}
total := len(s) + 2*hexCount
if buf.Cap() < total {
buf.Grow(total * 2)
}
t := buf.Bytes()[:total]
j := 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEscapeLUT[c] {
t[j] = '%'
t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
} else {
t[j] = c
j++
}
}
return t
} // copy from prometheus source code // NoAllocString convert []byte to string
func NoAllocString(buf []byte) string {
return *(*string)(unsafe.Pointer(&buf))
} // NoAllocBytes convert string to []byte
func NoAllocBytes(buf string) []byte {
// not safe: return *(*[]byte)(unsafe.Pointer(&buf))
x := (*reflect.StringHeader)(unsafe.Pointer(&buf))
h := reflect.SliceHeader{Data: x.Data, Len: x.Len, Cap: x.Len}
// nolint:all
return *(*[]byte)(unsafe.Pointer(&h))
}

使用的时候要重用 bytes.Buffer 对象。例如如下:

var testStr = "a=1&b=2&%%?_-/中文__-_.~:@+$"
// a%3D1%26b%3D2%26%25%25%3F_-%2F%E4%B8%AD%E6%96%87__-_.~%3A%40%2B%24 func TestFastQueryEscape(t *testing.T) {
s := url.QueryEscape(testStr)
t.Logf("%s", s)
target := &bytes.Buffer{}
target.Grow(1024)
out := FastQueryEscape(testStr, target)
t.Logf("%s", NoAllocString(out))
if s != NoAllocString(out) {
t.Error("not match")
}
}

【代码片段分享】比 url.QueryEscape 快 7.33 倍的 FastQueryEscape的更多相关文章

  1. runnable:在线IDE+代码片段分享

    在我之前的博客20个最好的在线IDE中列举过很多在线IDE,可以很方便的在云端执行代码,这样在你手头没有编译器时想试个小程序会非常有用. 今天介绍的这个网站runnable把在线IDE和代码片段结合了 ...

  2. 很棒的jQuery代码片段分享

    jQuery实现的内链接平滑滚动 不需要使用太复杂的插件,只要使用下载这段代码即可实现基于内部链接的平滑滚动 $('a[href^="#"]').bind('click.smoot ...

  3. 三行Python代码,让你的数据处理脚本快别人4倍

    Python是一门非常适合处理数据和自动化完成重复性工作的编程语言,我们在用数据训练机器学习模型之前,通常都需要对数据进行预处理,而Python就非常适合完成这项工作,比如需要重新调整几十万张图像的尺 ...

  4. 10 个实用的 jQuery 表单操作代码片段

    jQuery 绝对是一个伟大的开源JavaScript类库,是帮助我们快速和高效开发前端应用的利器.可能大家在日常的开发过程中常常会处理表单相关的 JavaScript,在今天这篇代码片段分享文章中, ...

  5. 10个超棒jQuery表单操作代码片段

    jQuery绝对是一个伟大的开源javascript类库,是帮助我们快速和高效开发前端应用的利器.可能大家在日常的开发过程中常常会处理表单相关的javascript,在今天这篇代码片段分享文章中,这里 ...

  6. 不可错过的10个超棒jQuery表单操作代码片段

    jQuery 绝对是一个伟大的开源javascript类库,是帮助我们快速和高效开发前端应用的利器.可能大家在日常的开发过程中常常会处理表单相关的 javascript,在今天这篇代码片段分享文章中, ...

  7. 微信小程序代码片段

    微信小程序代码片段是一种可分享的小项目,可用于分享小程序和小游戏的开发经验.展示组件和 API 的使用.复现开发问题等等.分享代码片段会得到一个链接,所有拥有此分享链接的人可以在工具中导入此代码片段. ...

  8. 经验分享:10个简单实用的 jQuery 代码片段

    尽管各种 JavaScirpt 框架和库层出不穷,jQuery 仍然是 Web 前端开发中最常用的工具库.今天,向大家分享我觉得在网站开发中10个简单实用的 jQuery 代码片段. 您可能感兴趣的相 ...

  9. 分享10个超实用的jQuery代码片段

    来源:GBin1.com jQuery以其强大的功能和简单的使用成为了前端开发者最喜欢的JS类库,在这里我们分享一组实用的jQuery代码片段,希望大家喜欢! jQuery平滑回到顶端效果 $(doc ...

  10. web 分享代码片段

    <div class="bshare-custom icon-medium-plus"><a title="分享到QQ空间" class=&q ...

随机推荐

  1. 补齐OLAP引擎短板!ByteHouse 是如何实现流批一体的?

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   计算机领域一直流传一句话--"没有银弹",这句话出自计算机科学家布鲁克斯<没有银弹& ...

  2. 涂色游戏Flood-it!(IDA star算法) - HDU 4127

    做题之前,可以先到下面这个网站玩一会游戏: https://unixpapa.com/floodit/?sz=14&nc=6 游戏开发里面,比较常用的一个搜索算法是寻路算法,寻路算法里面用的最 ...

  3. 第四届蓝桥杯(2013)C/C++大学A组省赛题解

    第一题:高斯日记 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天是高斯出生 ...

  4. java读取解析endnote文件

    有些项目中会要求代码解析endnote文献资料获取一些标准的信息,例如XX在某著名期刊上发表了某篇文章,关于发表文章的这个事情的描述就会给坐着一个endnote文件来记录文章名称.作者.期刊名称.出版 ...

  5. java基础-java面向对象-02-day09

    目录 1. 封装 2. 继承 2.1 什么是方法的重写 2.2 super 2.3 object详解 2.4 equals方法 3. 多态 4. final修饰符 5.抽象类 6. 接口 7. 内部类 ...

  6. hello world 的并发实现

    本篇文章将介绍 hello world 的并发实现,其中涉及到的知识有: 并发与并行 GPM 调度系统 并发与并行 并发不是并行.并发是同时管理很多事情,这些事情可能只做了一半就被暂停做别的事情了.而 ...

  7. 1. 常用的一些系统性能排查linux命令

    目录 一.CPU 1.1 top命令--CPU性能 1.2 负载 -- CPU 任务排队情况 1.3 vmstat -- CPU 繁忙程度 二.内存 2.1 top命令 三.IO 3.1 iostat ...

  8. ABP微服务系列学习-搭建自己的微服务结构(二)

    在解决方案根目录添加common.props,这个文件的作用是可以配置项目文件全局的一些属性,如忽略警告,全局PackageReference,语言版本等. <Project> <P ...

  9. 2023年春秋杯网络安全联赛冬季赛-CRYPTO MISC WP

    浅谈:*代表未做出的,赛后复现了一下.本次题目还是挺有意思的,比赛期间做啦俩.题目有很多值得学习的东西.顺便在此记录一下.继续努力吧!! CRYPTO not_wiener(中等) 题目附件 查看代码 ...

  10. [转帖]SMEMBERS:获取集合包含的所有元素

    https://www.bookstack.cn/read/redisguide/spilt.4.291fab46a3b4f05c.md SMEMBERS set 以下代码展示了如何使用 SMEMBE ...