encode_amd64.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. //go:build !appengine && !noasm && gc
  2. package s2
  3. import (
  4. "sync"
  5. "github.com/klauspost/compress/internal/race"
  6. )
  7. const hasAmd64Asm = true
  8. var encPools [4]sync.Pool
  9. // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It
  10. // assumes that the varint-encoded length of the decompressed bytes has already
  11. // been written.
  12. //
  13. // It also assumes that:
  14. //
  15. // len(dst) >= MaxEncodedLen(len(src)) &&
  16. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  17. func encodeBlock(dst, src []byte) (d int) {
  18. race.ReadSlice(src)
  19. race.WriteSlice(dst)
  20. const (
  21. // Use 12 bit table when less than...
  22. limit12B = 16 << 10
  23. // Use 10 bit table when less than...
  24. limit10B = 4 << 10
  25. // Use 8 bit table when less than...
  26. limit8B = 512
  27. )
  28. if len(src) >= 4<<20 {
  29. const sz, pool = 65536, 0
  30. tmp, ok := encPools[pool].Get().(*[sz]byte)
  31. if !ok {
  32. tmp = &[sz]byte{}
  33. }
  34. race.WriteSlice(tmp[:])
  35. defer encPools[pool].Put(tmp)
  36. return encodeBlockAsm(dst, src, tmp)
  37. }
  38. if len(src) >= limit12B {
  39. const sz, pool = 65536, 0
  40. tmp, ok := encPools[pool].Get().(*[sz]byte)
  41. if !ok {
  42. tmp = &[sz]byte{}
  43. }
  44. race.WriteSlice(tmp[:])
  45. defer encPools[pool].Put(tmp)
  46. return encodeBlockAsm4MB(dst, src, tmp)
  47. }
  48. if len(src) >= limit10B {
  49. const sz, pool = 16384, 1
  50. tmp, ok := encPools[pool].Get().(*[sz]byte)
  51. if !ok {
  52. tmp = &[sz]byte{}
  53. }
  54. race.WriteSlice(tmp[:])
  55. defer encPools[pool].Put(tmp)
  56. return encodeBlockAsm12B(dst, src, tmp)
  57. }
  58. if len(src) >= limit8B {
  59. const sz, pool = 4096, 2
  60. tmp, ok := encPools[pool].Get().(*[sz]byte)
  61. if !ok {
  62. tmp = &[sz]byte{}
  63. }
  64. race.WriteSlice(tmp[:])
  65. defer encPools[pool].Put(tmp)
  66. return encodeBlockAsm10B(dst, src, tmp)
  67. }
  68. if len(src) < minNonLiteralBlockSize {
  69. return 0
  70. }
  71. const sz, pool = 1024, 3
  72. tmp, ok := encPools[pool].Get().(*[sz]byte)
  73. if !ok {
  74. tmp = &[sz]byte{}
  75. }
  76. race.WriteSlice(tmp[:])
  77. defer encPools[pool].Put(tmp)
  78. return encodeBlockAsm8B(dst, src, tmp)
  79. }
  80. var encBetterPools [5]sync.Pool
  81. // encodeBlockBetter encodes a non-empty src to a guaranteed-large-enough dst. It
  82. // assumes that the varint-encoded length of the decompressed bytes has already
  83. // been written.
  84. //
  85. // It also assumes that:
  86. //
  87. // len(dst) >= MaxEncodedLen(len(src)) &&
  88. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  89. func encodeBlockBetter(dst, src []byte) (d int) {
  90. race.ReadSlice(src)
  91. race.WriteSlice(dst)
  92. const (
  93. // Use 12 bit table when less than...
  94. limit12B = 16 << 10
  95. // Use 10 bit table when less than...
  96. limit10B = 4 << 10
  97. // Use 8 bit table when less than...
  98. limit8B = 512
  99. )
  100. if len(src) > 4<<20 {
  101. const sz, pool = 589824, 0
  102. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  103. if !ok {
  104. tmp = &[sz]byte{}
  105. }
  106. race.WriteSlice(tmp[:])
  107. defer encBetterPools[pool].Put(tmp)
  108. return encodeBetterBlockAsm(dst, src, tmp)
  109. }
  110. if len(src) >= limit12B {
  111. const sz, pool = 589824, 0
  112. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  113. if !ok {
  114. tmp = &[sz]byte{}
  115. }
  116. race.WriteSlice(tmp[:])
  117. defer encBetterPools[pool].Put(tmp)
  118. return encodeBetterBlockAsm4MB(dst, src, tmp)
  119. }
  120. if len(src) >= limit10B {
  121. const sz, pool = 81920, 0
  122. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  123. if !ok {
  124. tmp = &[sz]byte{}
  125. }
  126. race.WriteSlice(tmp[:])
  127. defer encBetterPools[pool].Put(tmp)
  128. return encodeBetterBlockAsm12B(dst, src, tmp)
  129. }
  130. if len(src) >= limit8B {
  131. const sz, pool = 20480, 1
  132. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  133. if !ok {
  134. tmp = &[sz]byte{}
  135. }
  136. race.WriteSlice(tmp[:])
  137. defer encBetterPools[pool].Put(tmp)
  138. return encodeBetterBlockAsm10B(dst, src, tmp)
  139. }
  140. if len(src) < minNonLiteralBlockSize {
  141. return 0
  142. }
  143. const sz, pool = 5120, 2
  144. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  145. if !ok {
  146. tmp = &[sz]byte{}
  147. }
  148. race.WriteSlice(tmp[:])
  149. defer encBetterPools[pool].Put(tmp)
  150. return encodeBetterBlockAsm8B(dst, src, tmp)
  151. }
  152. // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It
  153. // assumes that the varint-encoded length of the decompressed bytes has already
  154. // been written.
  155. //
  156. // It also assumes that:
  157. //
  158. // len(dst) >= MaxEncodedLen(len(src)) &&
  159. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  160. func encodeBlockSnappy(dst, src []byte) (d int) {
  161. race.ReadSlice(src)
  162. race.WriteSlice(dst)
  163. const (
  164. // Use 12 bit table when less than...
  165. limit12B = 16 << 10
  166. // Use 10 bit table when less than...
  167. limit10B = 4 << 10
  168. // Use 8 bit table when less than...
  169. limit8B = 512
  170. )
  171. if len(src) > 65536 {
  172. const sz, pool = 65536, 0
  173. tmp, ok := encPools[pool].Get().(*[sz]byte)
  174. if !ok {
  175. tmp = &[sz]byte{}
  176. }
  177. race.WriteSlice(tmp[:])
  178. defer encPools[pool].Put(tmp)
  179. return encodeSnappyBlockAsm(dst, src, tmp)
  180. }
  181. if len(src) >= limit12B {
  182. const sz, pool = 65536, 0
  183. tmp, ok := encPools[pool].Get().(*[sz]byte)
  184. if !ok {
  185. tmp = &[sz]byte{}
  186. }
  187. race.WriteSlice(tmp[:])
  188. defer encPools[pool].Put(tmp)
  189. return encodeSnappyBlockAsm64K(dst, src, tmp)
  190. }
  191. if len(src) >= limit10B {
  192. const sz, pool = 16384, 1
  193. tmp, ok := encPools[pool].Get().(*[sz]byte)
  194. if !ok {
  195. tmp = &[sz]byte{}
  196. }
  197. race.WriteSlice(tmp[:])
  198. defer encPools[pool].Put(tmp)
  199. return encodeSnappyBlockAsm12B(dst, src, tmp)
  200. }
  201. if len(src) >= limit8B {
  202. const sz, pool = 4096, 2
  203. tmp, ok := encPools[pool].Get().(*[sz]byte)
  204. if !ok {
  205. tmp = &[sz]byte{}
  206. }
  207. race.WriteSlice(tmp[:])
  208. defer encPools[pool].Put(tmp)
  209. return encodeSnappyBlockAsm10B(dst, src, tmp)
  210. }
  211. if len(src) < minNonLiteralBlockSize {
  212. return 0
  213. }
  214. const sz, pool = 1024, 3
  215. tmp, ok := encPools[pool].Get().(*[sz]byte)
  216. if !ok {
  217. tmp = &[sz]byte{}
  218. }
  219. race.WriteSlice(tmp[:])
  220. defer encPools[pool].Put(tmp)
  221. return encodeSnappyBlockAsm8B(dst, src, tmp)
  222. }
  223. // encodeBlockSnappy encodes a non-empty src to a guaranteed-large-enough dst. It
  224. // assumes that the varint-encoded length of the decompressed bytes has already
  225. // been written.
  226. //
  227. // It also assumes that:
  228. //
  229. // len(dst) >= MaxEncodedLen(len(src)) &&
  230. // minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize
  231. func encodeBlockBetterSnappy(dst, src []byte) (d int) {
  232. race.ReadSlice(src)
  233. race.WriteSlice(dst)
  234. const (
  235. // Use 12 bit table when less than...
  236. limit12B = 16 << 10
  237. // Use 10 bit table when less than...
  238. limit10B = 4 << 10
  239. // Use 8 bit table when less than...
  240. limit8B = 512
  241. )
  242. if len(src) > 65536 {
  243. const sz, pool = 589824, 0
  244. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  245. if !ok {
  246. tmp = &[sz]byte{}
  247. }
  248. race.WriteSlice(tmp[:])
  249. defer encBetterPools[pool].Put(tmp)
  250. return encodeSnappyBetterBlockAsm(dst, src, tmp)
  251. }
  252. if len(src) >= limit12B {
  253. const sz, pool = 294912, 4
  254. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  255. if !ok {
  256. tmp = &[sz]byte{}
  257. }
  258. race.WriteSlice(tmp[:])
  259. defer encBetterPools[pool].Put(tmp)
  260. return encodeSnappyBetterBlockAsm64K(dst, src, tmp)
  261. }
  262. if len(src) >= limit10B {
  263. const sz, pool = 81920, 0
  264. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  265. if !ok {
  266. tmp = &[sz]byte{}
  267. }
  268. race.WriteSlice(tmp[:])
  269. defer encBetterPools[pool].Put(tmp)
  270. return encodeSnappyBetterBlockAsm12B(dst, src, tmp)
  271. }
  272. if len(src) >= limit8B {
  273. const sz, pool = 20480, 1
  274. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  275. if !ok {
  276. tmp = &[sz]byte{}
  277. }
  278. race.WriteSlice(tmp[:])
  279. defer encBetterPools[pool].Put(tmp)
  280. return encodeSnappyBetterBlockAsm10B(dst, src, tmp)
  281. }
  282. if len(src) < minNonLiteralBlockSize {
  283. return 0
  284. }
  285. const sz, pool = 5120, 2
  286. tmp, ok := encBetterPools[pool].Get().(*[sz]byte)
  287. if !ok {
  288. tmp = &[sz]byte{}
  289. }
  290. race.WriteSlice(tmp[:])
  291. defer encBetterPools[pool].Put(tmp)
  292. return encodeSnappyBetterBlockAsm8B(dst, src, tmp)
  293. }