index.coffee 5.1 KB
Newer Older
huahua committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
builder = require('../src/index')
git = require('git-state')
fs = require('fs')
path = require('path')
{ performance, PerformanceObserver } = require('perf_hooks')

global.xml = builder.create
global.doc = builder.begin

global.perf = (description, count, func) ->

  totalTime = 0

  callback = (userFunction) ->
    startTime = performance.now()
    for i in [1..count]
      userFunction()
    endTime = performance.now()
    totalTime += endTime - startTime
  func(callback)

  averageTime = totalTime / count

  version = require('../package.json').version
  working = gitWorking(gitDir)
  if working then version = version + "*"
  if not perfObj[version] then perfObj[version] = { }

  perfObj[version][description] = averageTime.toFixed(4)

readPerf = (filename) ->
  if not fs.existsSync(filename) then fs.closeSync(fs.openSync(filename, 'w'))
  str = fs.readFileSync(filename, 'utf8')
  if str then JSON.parse(str) else { }

runPerf = (dirPath) ->
  for file from walkDir(dirPath)
    filename = path.basename(file)
    if filename is "index.coffee" or filename is "perf.list" then continue
    require(file)

walkDir = (dirPath) ->
  for file in fs.readdirSync(dirPath)
    filePath = path.join(dirPath, file)
    stat = fs.statSync(filePath)
    if stat.isFile() then yield filePath else if stat.isDirectory() then yield from walkDir(filePath)
  return undefined

gitWorking = (dirPath) ->
  return git.isGitSync(dirPath) and git.dirtySync(dirPath)

printPerf = (perfObj) ->
  sorted = sortByVersion(perfObj)

  for sortedItems in sorted
    version = sortedItems.version
    items = sortedItems.item
    sortedItem = sortByDesc(items)

    if parseVersion(version)[3]
      console.log "\x1b[4mv%s (Working Tree):\x1b[0m", version
    else
      console.log "\x1b[4mv%s:\x1b[0m", version

    longestDescription = 0
    for item in sortedItem
      descriptionLength = item.description.length
      if descriptionLength > longestDescription 
        longestDescription = descriptionLength

    for item in sortedItem
      description = item.description
      averageTime = item.averageTime
      prevItem = findPrevPerf(sorted, version, description)
      if prevItem
        if averageTime < prevItem.item[description]
          console.log "  - \x1b[36m%s\x1b[0m \x1b[1m\x1b[32m%s\x1b[0m ms (v%s was \x1b[1m%s\x1b[0m ms, -\x1b[1m%s\x1b[0m%)", padRight(description, longestDescription), averageTime, prevItem.version, prevItem.item[description], (-100*(averageTime - prevItem.item[description]) / prevItem.item[description]).toFixed(0)
        else if averageTime > prevItem.item[description]
          console.log "  - \x1b[36m%s\x1b[0m \x1b[1m\x1b[31m%s\x1b[0m ms (v%s was \x1b[1m%s\x1b[0m ms, +\x1b[1m%s\x1b[0m%)", padRight(description, longestDescription), averageTime, prevItem.version, prevItem.item[description], (100*(averageTime - prevItem.item[description]) / prevItem.item[description]).toFixed(0)
        else
          console.log "  - \x1b[36m%s\x1b[0m \x1b[1m%s\x1b[0m ms (v%s was \x1b[1m%s\x1b[0m ms,  \x1b[1m%s\x1b[0m%)", padRight(description, longestDescription), averageTime, prevItem.version, prevItem.item[description], (100*(averageTime - prevItem.item[description]) / prevItem.item[description]).toFixed(0)
      else
        console.log "  - \x1b[36m%s\x1b[0m \x1b[1m%s\x1b[0m ms (no previous result)", padRight(description, longestDescription), averageTime

padRight = (str, len) ->
  str + " ".repeat(len - str.length)

writePerf = (filename, perfObj) ->
  writePerfObj = { }
  for version, items of perfObj
    if not parseVersion(version)[3]
      writePerfObj[version] = items
  fs.writeFileSync(filename, JSON.stringify(writePerfObj, null, 2) , 'utf-8')

findPrevPerf = (sorted, version, description) ->
  prev = undefined
  for item in sorted
    if compareVersion(item.version, version) is -1
      if item.item[description]
        prev = item
  return prev

sortByVersion = (perfObj) ->
  sorted = []
  for version, items of perfObj
    sorted.push
      version: version
      item: items
  sorted.sort (item1, item2) ->
    compareVersion(item1.version, item2.version)

sortByDesc = (item) ->
  sorted = []
  for description, averageTime of item
    sorted.push
      description: description
      averageTime: averageTime
  sorted.sort (item1, item2) ->
    if item1.description < item2.description then -1 else 1

parseVersion = (version) ->
  isDirty = version[version.length - 1] is "*"
  if isDirty then version = version.substr(0, version.length - 1)
  v = version.split('.')
  v.push(isDirty)
  return v

compareVersion = (v1, v2) ->
  v1 = parseVersion(v1)
  v2 = parseVersion(v2)

  if v1[0] < v2[0]
    -1
  else if v1[0] > v2[0]
    1
  else # v1[0] = v2[0]
    if v1[1] < v2[1]
      -1
    else if v1[1] > v2[1]
      1
    else # v1[1] = v2[1]
      if v1[2] < v2[2]
        -1
      else if v1[2] > v2[2]
        1
      else # v1[2] = v2[2]
        if v1[3] and not v2[3]
          1
        else if v2[3] and not v1[3]
          -1
        else
          0


perfDir = __dirname
gitDir = path.resolve(__dirname, '..')
perfFile = path.join(perfDir, './perf.list')
perfObj = readPerf(perfFile)
runPerf(perfDir)
printPerf(perfObj)
writePerf(perfFile, perfObj)