Some checks failed
		
		
	
	Detach Plugins / check (FlyGrep.vim) (push) Has been cancelled
				
			Detach Plugins / check (GitHub.vim) (push) Has been cancelled
				
			Detach Plugins / check (JavaUnit.vim) (push) Has been cancelled
				
			Detach Plugins / check (SourceCounter.vim) (push) Has been cancelled
				
			Detach Plugins / check (cpicker.nvim) (push) Has been cancelled
				
			Detach Plugins / check (dein-ui.vim) (push) Has been cancelled
				
			Detach Plugins / check (git.vim) (push) Has been cancelled
				
			Detach Plugins / check (iedit.vim) (push) Has been cancelled
				
			Detach Plugins / check (scrollbar.vim) (push) Has been cancelled
				
			Detach Plugins / check (vim-chat) (push) Has been cancelled
				
			Detach Plugins / check (vim-cheat) (push) Has been cancelled
				
			Detach Plugins / check (vim-todo) (push) Has been cancelled
				
			Detach Plugins / check (xmake.vim) (push) Has been cancelled
				
			test / Linux (nvim, nightly) (push) Has been cancelled
				
			test / Linux (nvim, v0.3.8) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.3) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.4) (push) Has been cancelled
				
			test / Linux (nvim, v0.5.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.5.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.6.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.6.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.7.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.7.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.3) (push) Has been cancelled
				
			test / Linux (nvim, v0.9.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.9.1) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.052) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.1689) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.629) (push) Has been cancelled
				
			test / Linux (true, vim, v8.0.0027) (push) Has been cancelled
				
			test / Linux (true, vim, v8.0.0183) (push) Has been cancelled
				
			test / Linux (vim, nightly) (push) Has been cancelled
				
			test / Linux (vim, v8.0.0184) (push) Has been cancelled
				
			test / Linux (vim, v8.0.1453) (push) Has been cancelled
				
			test / Linux (vim, v8.1.2269) (push) Has been cancelled
				
			test / Linux (vim, v8.2.2434) (push) Has been cancelled
				
			test / Linux (vim, v8.2.3995) (push) Has been cancelled
				
			test / Windows (nvim, nightly) (push) Has been cancelled
				
			test / Windows (nvim, v0.3.8) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.3) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.4) (push) Has been cancelled
				
			test / Windows (nvim, v0.5.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.5.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.6.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.6.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.7.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.7.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.3) (push) Has been cancelled
				
			test / Windows (nvim, v0.9.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.9.1) (push) Has been cancelled
				
			test / Windows (vim, nightly) (push) Has been cancelled
				
			test / Windows (vim, v7.4.1185) (push) Has been cancelled
				
			test / Windows (vim, v7.4.1689) (push) Has been cancelled
				
			test / Windows (vim, v8.0.0027) (push) Has been cancelled
				
			test / Windows (vim, v8.0.1453) (push) Has been cancelled
				
			test / Windows (vim, v8.1.2269) (push) Has been cancelled
				
			test / Windows (vim, v8.2.2434) (push) Has been cancelled
				
			test / Windows (vim, v8.2.3995) (push) Has been cancelled
				
			docker / docker (push) Has been cancelled
				
			mirror / check (coding) (push) Has been cancelled
				
			mirror / check (gitee) (push) Has been cancelled
				
			mirror / check (gitlab) (push) Has been cancelled
				
			
		
			
				
	
	
		
			313 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			313 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
----------------------------------------------------------------------------
 | 
						|
-- LuaJIT profiler.
 | 
						|
--
 | 
						|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
 | 
						|
-- Released under the MIT license. See Copyright Notice in luajit.h
 | 
						|
----------------------------------------------------------------------------
 | 
						|
--
 | 
						|
-- This module is a simple command line interface to the built-in
 | 
						|
-- low-overhead profiler of LuaJIT.
 | 
						|
--
 | 
						|
-- The lower-level API of the profiler is accessible via the "jit.profile"
 | 
						|
-- module or the luaJIT_profile_* C API.
 | 
						|
--
 | 
						|
-- Example usage:
 | 
						|
--
 | 
						|
--   luajit -jp myapp.lua
 | 
						|
--   luajit -jp=s myapp.lua
 | 
						|
--   luajit -jp=-s myapp.lua
 | 
						|
--   luajit -jp=vl myapp.lua
 | 
						|
--   luajit -jp=G,profile.txt myapp.lua
 | 
						|
--
 | 
						|
-- The following dump features are available:
 | 
						|
--
 | 
						|
--   f  Stack dump: function name, otherwise module:line. Default mode.
 | 
						|
--   F  Stack dump: ditto, but always prepend module.
 | 
						|
--   l  Stack dump: module:line.
 | 
						|
--   <number> stack dump depth (callee < caller). Default: 1.
 | 
						|
--   -<number> Inverse stack dump depth (caller > callee).
 | 
						|
--   s  Split stack dump after first stack level. Implies abs(depth) >= 2.
 | 
						|
--   p  Show full path for module names.
 | 
						|
--   v  Show VM states. Can be combined with stack dumps, e.g. vf or fv.
 | 
						|
--   z  Show zones. Can be combined with stack dumps, e.g. zf or fz.
 | 
						|
--   r  Show raw sample counts. Default: show percentages.
 | 
						|
--   a  Annotate excerpts from source code files.
 | 
						|
--   A  Annotate complete source code files.
 | 
						|
--   G  Produce raw output suitable for graphical tools (e.g. flame graphs).
 | 
						|
--   m<number> Minimum sample percentage to be shown. Default: 3.
 | 
						|
--   i<number> Sampling interval in milliseconds. Default: 10.
 | 
						|
--
 | 
						|
----------------------------------------------------------------------------
 | 
						|
 | 
						|
-- Cache some library functions and objects.
 | 
						|
local jit = require("jit")
 | 
						|
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
 | 
						|
local profile = require("jit.profile")
 | 
						|
local vmdef = require("jit.vmdef")
 | 
						|
local math = math
 | 
						|
local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor
 | 
						|
local sort, format = table.sort, string.format
 | 
						|
local stdout = io.stdout
 | 
						|
local zone -- Load jit.zone module on demand.
 | 
						|
 | 
						|
-- Output file handle.
 | 
						|
local out
 | 
						|
 | 
						|
------------------------------------------------------------------------------
 | 
						|
 | 
						|
local prof_ud
 | 
						|
local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth
 | 
						|
local prof_ann, prof_count1, prof_count2, prof_samples
 | 
						|
 | 
						|
local map_vmmode = {
 | 
						|
  N = "Compiled",
 | 
						|
  I = "Interpreted",
 | 
						|
  C = "C code",
 | 
						|
  G = "Garbage Collector",
 | 
						|
  J = "JIT Compiler",
 | 
						|
}
 | 
						|
 | 
						|
-- Profiler callback.
 | 
						|
local function prof_cb(th, samples, vmmode)
 | 
						|
  prof_samples = prof_samples + samples
 | 
						|
  local key_stack, key_stack2, key_state
 | 
						|
  -- Collect keys for sample.
 | 
						|
  if prof_states then
 | 
						|
    if prof_states == "v" then
 | 
						|
      key_state = map_vmmode[vmmode] or vmmode
 | 
						|
    else
 | 
						|
      key_state = zone:get() or "(none)"
 | 
						|
    end
 | 
						|
  end
 | 
						|
  if prof_fmt then
 | 
						|
    key_stack = profile.dumpstack(th, prof_fmt, prof_depth)
 | 
						|
    key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x)
 | 
						|
      return vmdef.ffnames[tonumber(x)]
 | 
						|
    end)
 | 
						|
    if prof_split == 2 then
 | 
						|
      local k1, k2 = key_stack:match("(.-) [<>] (.*)")
 | 
						|
      if k2 then key_stack, key_stack2 = k1, k2 end
 | 
						|
    elseif prof_split == 3 then
 | 
						|
      key_stack2 = profile.dumpstack(th, "l", 1)
 | 
						|
    end
 | 
						|
  end
 | 
						|
  -- Order keys.
 | 
						|
  local k1, k2
 | 
						|
  if prof_split == 1 then
 | 
						|
    if key_state then
 | 
						|
      k1 = key_state
 | 
						|
      if key_stack then k2 = key_stack end
 | 
						|
    end
 | 
						|
  elseif key_stack then
 | 
						|
    k1 = key_stack
 | 
						|
    if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end
 | 
						|
  end
 | 
						|
  -- Coalesce samples in one or two levels.
 | 
						|
  if k1 then
 | 
						|
    local t1 = prof_count1
 | 
						|
    t1[k1] = (t1[k1] or 0) + samples
 | 
						|
    if k2 then
 | 
						|
      local t2 = prof_count2
 | 
						|
      local t3 = t2[k1]
 | 
						|
      if not t3 then t3 = {}; t2[k1] = t3 end
 | 
						|
      t3[k2] = (t3[k2] or 0) + samples
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------------------------------------
 | 
						|
 | 
						|
-- Show top N list.
 | 
						|
local function prof_top(count1, count2, samples, indent)
 | 
						|
  local t, n = {}, 0
 | 
						|
  for k in pairs(count1) do
 | 
						|
    n = n + 1
 | 
						|
    t[n] = k
 | 
						|
  end
 | 
						|
  sort(t, function(a, b) return count1[a] > count1[b] end)
 | 
						|
  for i=1,n do
 | 
						|
    local k = t[i]
 | 
						|
    local v = count1[k]
 | 
						|
    local pct = floor(v*100/samples + 0.5)
 | 
						|
    if pct < prof_min then break end
 | 
						|
    if not prof_raw then
 | 
						|
      out:write(format("%s%2d%%  %s\n", indent, pct, k))
 | 
						|
    elseif prof_raw == "r" then
 | 
						|
      out:write(format("%s%5d  %s\n", indent, v, k))
 | 
						|
    else
 | 
						|
      out:write(format("%s %d\n", k, v))
 | 
						|
    end
 | 
						|
    if count2 then
 | 
						|
      local r = count2[k]
 | 
						|
      if r then
 | 
						|
	prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and "  -- " or
 | 
						|
			    (prof_depth < 0 and "  -> " or "  <- "))
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
-- Annotate source code
 | 
						|
local function prof_annotate(count1, samples)
 | 
						|
  local files = {}
 | 
						|
  local ms = 0
 | 
						|
  for k, v in pairs(count1) do
 | 
						|
    local pct = floor(v*100/samples + 0.5)
 | 
						|
    ms = math.max(ms, v)
 | 
						|
    if pct >= prof_min then
 | 
						|
      local file, line = k:match("^(.*):(%d+)$")
 | 
						|
      if not file then file = k; line = 0 end
 | 
						|
      local fl = files[file]
 | 
						|
      if not fl then fl = {}; files[file] = fl; files[#files+1] = file end
 | 
						|
      line = tonumber(line)
 | 
						|
      fl[line] = prof_raw and v or pct
 | 
						|
    end
 | 
						|
  end
 | 
						|
  sort(files)
 | 
						|
  local fmtv, fmtn = " %3d%% | %s\n", "      | %s\n"
 | 
						|
  if prof_raw then
 | 
						|
    local n = math.max(5, math.ceil(math.log10(ms)))
 | 
						|
    fmtv = "%"..n.."d | %s\n"
 | 
						|
    fmtn = (" "):rep(n).." | %s\n"
 | 
						|
  end
 | 
						|
  local ann = prof_ann
 | 
						|
  for _, file in ipairs(files) do
 | 
						|
    local f0 = file:byte()
 | 
						|
    if f0 == 40 or f0 == 91 then
 | 
						|
      out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file))
 | 
						|
      break
 | 
						|
    end
 | 
						|
    local fp, err = io.open(file)
 | 
						|
    if not fp then
 | 
						|
      out:write(format("====== ERROR: %s: %s\n", file, err))
 | 
						|
      break
 | 
						|
    end
 | 
						|
    out:write(format("\n====== %s ======\n", file))
 | 
						|
    local fl = files[file]
 | 
						|
    local n, show = 1, false
 | 
						|
    if ann ~= 0 then
 | 
						|
      for i=1,ann do
 | 
						|
	if fl[i] then show = true; out:write("@@ 1 @@\n"); break end
 | 
						|
      end
 | 
						|
    end
 | 
						|
    for line in fp:lines() do
 | 
						|
      if line:byte() == 27 then
 | 
						|
	out:write("[Cannot annotate bytecode file]\n")
 | 
						|
	break
 | 
						|
      end
 | 
						|
      local v = fl[n]
 | 
						|
      if ann ~= 0 then
 | 
						|
	local v2 = fl[n+ann]
 | 
						|
	if show then
 | 
						|
	  if v2 then show = n+ann elseif v then show = n
 | 
						|
	  elseif show+ann < n then show = false end
 | 
						|
	elseif v2 then
 | 
						|
	  show = n+ann
 | 
						|
	  out:write(format("@@ %d @@\n", n))
 | 
						|
	end
 | 
						|
	if not show then goto next end
 | 
						|
      end
 | 
						|
      if v then
 | 
						|
	out:write(format(fmtv, v, line))
 | 
						|
      else
 | 
						|
	out:write(format(fmtn, line))
 | 
						|
      end
 | 
						|
    ::next::
 | 
						|
      n = n + 1
 | 
						|
    end
 | 
						|
    fp:close()
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------------------------------------
 | 
						|
 | 
						|
-- Finish profiling and dump result.
 | 
						|
local function prof_finish()
 | 
						|
  if prof_ud then
 | 
						|
    profile.stop()
 | 
						|
    local samples = prof_samples
 | 
						|
    if samples == 0 then
 | 
						|
      if prof_raw ~= true then out:write("[No samples collected]\n") end
 | 
						|
      return
 | 
						|
    end
 | 
						|
    if prof_ann then
 | 
						|
      prof_annotate(prof_count1, samples)
 | 
						|
    else
 | 
						|
      prof_top(prof_count1, prof_count2, samples, "")
 | 
						|
    end
 | 
						|
    prof_count1 = nil
 | 
						|
    prof_count2 = nil
 | 
						|
    prof_ud = nil
 | 
						|
    if out ~= stdout then out:close() end
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
-- Start profiling.
 | 
						|
local function prof_start(mode)
 | 
						|
  local interval = ""
 | 
						|
  mode = mode:gsub("i%d*", function(s) interval = s; return "" end)
 | 
						|
  prof_min = 3
 | 
						|
  mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end)
 | 
						|
  prof_depth = 1
 | 
						|
  mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end)
 | 
						|
  local m = {}
 | 
						|
  for c in mode:gmatch(".") do m[c] = c end
 | 
						|
  prof_states = m.z or m.v
 | 
						|
  if prof_states == "z" then zone = require("jit.zone") end
 | 
						|
  local scope = m.l or m.f or m.F or (prof_states and "" or "f")
 | 
						|
  local flags = (m.p or "")
 | 
						|
  prof_raw = m.r
 | 
						|
  if m.s then
 | 
						|
    prof_split = 2
 | 
						|
    if prof_depth == -1 or m["-"] then prof_depth = -2
 | 
						|
    elseif prof_depth == 1 then prof_depth = 2 end
 | 
						|
  elseif mode:find("[fF].*l") then
 | 
						|
    scope = "l"
 | 
						|
    prof_split = 3
 | 
						|
  else
 | 
						|
    prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0
 | 
						|
  end
 | 
						|
  prof_ann = m.A and 0 or (m.a and 3)
 | 
						|
  if prof_ann then
 | 
						|
    scope = "l"
 | 
						|
    prof_fmt = "pl"
 | 
						|
    prof_split = 0
 | 
						|
    prof_depth = 1
 | 
						|
  elseif m.G and scope ~= "" then
 | 
						|
    prof_fmt = flags..scope.."Z;"
 | 
						|
    prof_depth = -100
 | 
						|
    prof_raw = true
 | 
						|
    prof_min = 0
 | 
						|
  elseif scope == "" then
 | 
						|
    prof_fmt = false
 | 
						|
  else
 | 
						|
    local sc = prof_split == 3 and m.f or m.F or scope
 | 
						|
    prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ")
 | 
						|
  end
 | 
						|
  prof_count1 = {}
 | 
						|
  prof_count2 = {}
 | 
						|
  prof_samples = 0
 | 
						|
  profile.start(scope:lower()..interval, prof_cb)
 | 
						|
  prof_ud = newproxy(true)
 | 
						|
  getmetatable(prof_ud).__gc = prof_finish
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------------------------------------
 | 
						|
 | 
						|
local function start(mode, outfile)
 | 
						|
  if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end
 | 
						|
  if outfile then
 | 
						|
    out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
 | 
						|
  else
 | 
						|
    out = stdout
 | 
						|
  end
 | 
						|
  prof_start(mode or "f")
 | 
						|
end
 | 
						|
 | 
						|
-- Public module functions.
 | 
						|
return {
 | 
						|
  start = start, -- For -j command line option.
 | 
						|
  stop = prof_finish
 | 
						|
}
 | 
						|
 |