bench.app.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Created by Wu Jian Ping on - 2022/07/22.
  3. */
  4. const Searcher = require('..')
  5. const { ArgumentParser } = require('argparse')
  6. const readline = require('linebyline')
  7. // 处理输入参数
  8. const parser = new ArgumentParser({
  9. add_help: true,
  10. description: 'ip2region benchmark app',
  11. prog: 'node test.app.js',
  12. usage: 'Usage %(prog)s [command options]'
  13. })
  14. parser.add_argument('--db', { help: 'ip2region binary xdb file path, default: ../../data/ip2region.xdb' })
  15. parser.add_argument('--src', { help: 'source ip text file path, default: ../../data/ip.merge.txt' })
  16. parser.add_argument('--cache-policy', { help: 'cache policy: file/vectorIndex/content, default: content' })
  17. const args = parser.parse_args()
  18. const dbPath = args.db || '../../data/ip2region.xdb'
  19. const src = args.src || '../../data/ip.merge.txt'
  20. const cachePolicy = args.cache_policy || 'content'
  21. // 创建searcher对象
  22. const createSearcher = () => {
  23. let searcher = null
  24. let vectorIndex = null
  25. let buffer = null
  26. switch (cachePolicy) {
  27. case 'file':
  28. searcher = Searcher.newWithFileOnly(dbPath)
  29. break
  30. case 'vectorIndex':
  31. vectorIndex = Searcher.loadVectorIndexFromFile(dbPath)
  32. searcher = Searcher.newWithVectorIndex(dbPath, vectorIndex)
  33. break
  34. default:
  35. buffer = Searcher.loadContentFromFile(dbPath)
  36. searcher = Searcher.newWithBuffer(buffer)
  37. }
  38. console.log('options: ')
  39. console.log(` dbPath: ${dbPath}`)
  40. console.log(` src: ${dbPath}`)
  41. console.log(` cache-policy: ${cachePolicy}`)
  42. console.log('')
  43. return searcher
  44. }
  45. const ipToInt = ip => {
  46. // 切割IP
  47. const ps = ip.split('.')
  48. // 将各段转成int
  49. const i0 = parseInt(ps[0])
  50. const i1 = parseInt(ps[1])
  51. const i2 = parseInt(ps[2])
  52. const i3 = parseInt(ps[3])
  53. // 假如使用移位操作的话,这边可能产生负数
  54. return i0 * 256 * 256 * 256 + i1 * 256 * 256 + i2 * 256 + i3
  55. }
  56. const intToIp = ip => {
  57. const i0 = Math.floor(ip / (256 * 256 * 256))
  58. const i1 = Math.floor((ip % (256 * 256 * 256)) / (256 * 256))
  59. const i2 = Math.floor((ip % (256 * 256)) / 256)
  60. const i3 = ip % 256
  61. return `${i0}.${i1}.${i2}.${i3}`
  62. }
  63. const searcher = createSearcher()
  64. // 开始时间
  65. const startTime = process.hrtime()
  66. let total = 0
  67. // 程序主入口
  68. const main = async () => {
  69. const rl = readline(src)
  70. rl
  71. .on('line', async (line, lineCount, byteCount) => {
  72. try {
  73. const list = line.split('|')
  74. const sip = list[0]
  75. const eip = list[1]
  76. if (!Searcher.isValidIp(sip)) {
  77. throw new Error(`IP: ${sip} is invalid`)
  78. }
  79. if (!Searcher.isValidIp(eip)) {
  80. throw new Error(`IP: ${eip} is invalid`)
  81. }
  82. const sipInt = ipToInt(sip)
  83. const eipInt = ipToInt(eip)
  84. if (sipInt > eipInt) {
  85. throw new Error(`start ip(${sip}) should not be greater than end ip(${eip})`)
  86. }
  87. const mipInt = Math.floor((sipInt + eipInt) / 2)
  88. const mip = intToIp(mipInt)
  89. const mipLeftInt = Math.floor((sipInt + mipInt) / 2)
  90. const mipLeft = intToIp(mipLeftInt)
  91. const mipRightInt = Math.floor((mipInt + eipInt) / 2)
  92. const mipRight = intToIp(mipRightInt)
  93. const arr = [sip, mipLeft, mip, mipRight, eip]
  94. for (let i = 0; i < arr.length; ++i) {
  95. const target = arr[i]
  96. const info = await searcher.search(target)
  97. const region = list.slice(2, list.length).join('|')
  98. // check the region info
  99. if (region !== info.region) {
  100. throw new Error(`failed search(${mip}) with (${region} != ${info.region})`)
  101. }
  102. total++
  103. }
  104. } catch (err) {
  105. console.log(err)
  106. process.exit(1)
  107. }
  108. })
  109. .on('error', err => {
  110. console.log(err)
  111. process.exit(1)
  112. })
  113. }
  114. process.on('exit', code => {
  115. if (code === 0) {
  116. // 这边只算个总时间就够了
  117. const diff = process.hrtime(startTime)
  118. const totalInNS = diff[0] * 1e9 + diff[1]
  119. console.log(`Bench finished, {cachePolicy: ${cachePolicy}, total: ${total}, took: ${totalInNS / 1e9}s, cost: ${total === 0 ? 0 : (totalInNS / 1e3) / total}μs/op}`)
  120. }
  121. })
  122. main()