openos 1.6.6

More memory savings, significant boot time savings

**Memory Savings**
The largest library in terms of cost in bytes in 1.6.5 was /lib/filesystem. Most of this library is not needed for boot, and in 1.6.6 the library is half loaded for boot with a delay load of the rest of the library when needed. There are also other minor memory improvements, see **Changes** for details

**Boot Time**
This update also introduces a newly written /bin/sh.lua that takes advantage of a common stdio system. This work was primary done to reduce memory needed to load the shell. However, during development of a simplified /bin/sh, I found that the /bin/source, /etc/profile, and /home/.shrc feature added to openos 1.6 had a significant boot time cost. I began optimizing /bin/source heavily and found that I could not make sufficient speed improvements due to the nature of how shell commands execute. Thus /etc/profile has been removed in favor of /etc/profile.lua, a script that sets up the environment the same but as a lua script. ~/.shrc is still honored if it exists on a system, and is sourced (/bin/source) as a set of shell commands. This change speeds up boot time from floppy by 3s, and on hdds by 1s.

**Possible Breaking Changes**
/etc/profile has been moved to /etc/profile.lua, but /home/.shrc is still sourced as shell script commands.

**Changes**
* /bin/sh.lua rewrite that takes advantage of standard io and uses the new /etc/profile.lua shaving 6s off boot time
* /bin/source.lua improve performance by reducing the number of processes created
* move /etc/profile to /etc/profile.lua and recode the actions in lua-form.
* move all ~/.shrc actions to /etc/profile.lua for performance reasons
* move motd to start of /etc/profile.lua to get the shell display as soon as possible
* update greetings that referenced /etc/profile to properly refer to /etc/profile.lua now
* update openos version to 1.6.6 to respect the impact of these changes
This commit is contained in:
payonel 2017-06-25 22:58:54 -07:00
parent 83a37af8cb
commit c988b44f66
12 changed files with 90 additions and 103 deletions

View File

@ -4,7 +4,7 @@ local args, options = shell.parse(...)
local ec, error_prefix = 0, "alias:"
if options.help then
print(string.format("Usage: alias: [name[=value] ... ]", cmd_name))
print(string.format("Usage: alias: [name[=value] ... ]"))
return
end
@ -53,7 +53,7 @@ if not next(args) then -- no args
print(string.format("alias %s='%s'", k, v))
end
else
for k,v in pairs(args) do
for _,v in ipairs(args) do
checkArg(1,v,"string")
handlePair(splitPair(v))
end

View File

@ -2,7 +2,6 @@ local keyboard = require("keyboard")
local shell = require("shell")
local term = require("term") -- TODO use tty and cursor position instead of global area and gpu
local text = require("text")
local unicode = require("unicode")
if not io.output().tty then
return loadfile(shell.resolve("cat", "lua"), "bt", _G)(...)
@ -28,7 +27,7 @@ end
local line = nil
local function readlines(num)
local x, y, w, h = term.getGlobalArea()
local _, _, w, h = term.getGlobalArea()
num = num or (h - 1)
for _ = 1, num do
if not line then
@ -52,7 +51,7 @@ while true do
return
end
while true do
local event, address, char, code = term.pull("key_down")
local _, _, _, code = term.pull("key_down")
if code == keyboard.keys.q then
term.clearLine()
return

View File

@ -5,70 +5,50 @@ local text = require("text")
local sh = require("sh")
local input = table.pack(...)
local args, options = shell.parse(select(3,table.unpack(input)))
local args = shell.parse(select(3,table.unpack(input)))
if input[2] then
table.insert(args, 1, input[2])
end
local history = {hint = sh.hintHandler}
shell.prime()
local update_gpu = io.output().tty
local interactive = io.input().tty
local foreground
if #args == 0 and (io.stdin.tty or options.i) and not options.c then
-- interactive shell.
-- source profile
if not tty.isAvailable() then event.pull("term_available") end
loadfile(shell.resolve("source","lua"))("/etc/profile")
if #args == 0 then
while true do
if not tty.isAvailable() then -- don't clear unless we lost the term
if update_gpu then
while not tty.isAvailable() do
event.pull("term_available")
end
tty.clear()
end
local gpu = tty.gpu()
while tty.isAvailable() do
local foreground = gpu.setForeground(0xFF0000)
io.write(sh.expand(os.getenv("PS1") or "$ "))
gpu.setForeground(foreground)
tty.setCursorBlink(true)
local command = tty.read(history)
if not command then
if command == false then
break -- soft interrupt
end
io.write("exit\n") -- pipe closed
return -- eof
if not foreground and interactive then -- first time run AND interactive
dofile("/etc/profile.lua")
end
foreground = tty.gpu().setForeground(0xFF0000)
io.write(sh.expand(os.getenv("PS1") or "$ "))
tty.gpu().setForeground(foreground)
tty.setCursorBlink(true)
end
local command = tty.read(history)
if command then
command = text.trim(command)
if command == "exit" then
return
elseif command ~= "" then
local result, reason = sh.execute(_ENV, command)
if tty.getCursor() > 1 then
print()
if update_gpu and tty.getCursor() > 1 then
io.write("\n")
end
if not result then
io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n")
end
end
end
end
elseif #args == 0 and not io.stdin.tty then
while true do
io.write(sh.expand(os.getenv("PS1") or "$ "))
local command = io.read("*l")
if not command then
command = "exit"
io.write(command,"\n")
end
command = text.trim(command)
if command == "exit" then
return
elseif command ~= "" then
local result, reason = os.execute(command)
if not result then
io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n")
elseif command == nil then -- command==false is a soft interrupt, ignore it
if interactive then
io.write("exit\n") -- pipe closed
end
return -- eof
end
end
else

View File

@ -1,6 +1,5 @@
local shell = require("shell")
local fs = require("filesystem")
local sh = require("sh")
local process = require("process")
local args, options = shell.parse(...)
@ -9,23 +8,25 @@ if #args ~= 1 then
return 1
end
local file, reason = io.open(args[1], "r")
local file, open_reason = io.open(args[1], "r")
if not file then
if not options.q then
io.stderr:write(string.format("could not source %s because: %s\n", args[1], reason));
io.stderr:write(string.format("could not source %s because: %s\n", args[1], open_reason));
end
return 1
else
local status, reason = xpcall(function()
repeat
local line = file:read()
if line then
sh.execute(nil, line)
end
until not line
end, function(msg) return {msg, debug.traceback()} end)
file:close()
if not status and reason then assert(false, tostring(reason[1]) .."\n".. tostring(reason[2])) end
end
local current_data = process.info().data
local source_proc = process.load((assert(os.getenv("SHELL"), "no $SHELL set")))
local source_data = process.list[source_proc].data
source_data.aliases = current_data.aliases -- hacks to propogate sub shell env changes
source_data.vars = current_data.vars
source_data.io[0] = file -- set stdin to the file
if options.q then
source_data.io[1] = {tty=false,write=function()end} -- set stdin to the file
end
process.internal.continue(source_proc)
file:close() -- should have closed when the process closed, but just to be sure

View File

@ -2,9 +2,9 @@ function loadfile(filename, ...)
if filename:sub(1,1) ~= "/" then
filename = (os.getenv("PWD") or "/") .. "/" .. filename
end
local handle, reason = require("filesystem").open(filename)
local handle, open_reason = require("filesystem").open(filename)
if not handle then
return nil, reason
return nil, open_reason
end
local buffer = {}
while true do

View File

@ -1,26 +0,0 @@
alias dir=ls
alias move=mv
alias rename=mv
alias copy=cp
alias del=rm
alias md=mkdir
alias cls=clear
alias rs=redstone
alias view=edit\ -r
alias help=man
alias cp=cp\ -i
set EDITOR=/bin/edit
set HISTSIZE=10
set HOME=/home
set IFS=\
set MANPATH=/usr/man:.
set PAGER=/bin/more
set PS1='$HOSTNAME$HOSTNAME_SEPARATOR$PWD # '
set PWD=/
set LS_COLORS="{FILE=0xFFFFFF,DIR=0x66CCFF,LINK=0xFFAA00,['*.lua']=0x00FF00}"
cd $HOME
clear
/etc/motd
source $HOME/.shrc -q

View File

@ -0,0 +1,38 @@
local shell = require("shell")
local tty = require("tty")
local fs = require("filesystem")
tty.clear()
dofile("/etc/motd")
shell.setAlias("dir", "ls")
shell.setAlias("move", "mv")
shell.setAlias("rename", "mv")
shell.setAlias("copy", "cp")
shell.setAlias("del", "rm")
shell.setAlias("md", "mkdir")
shell.setAlias("cls", "clear")
shell.setAlias("rs", "redstone")
shell.setAlias("view", "edit -r")
shell.setAlias("help", "man")
shell.setAlias("cp", "cp -i")
shell.setAlias("l", "ls -lhp")
shell.setAlias("..", "cd ..")
shell.setAlias("df", "df -h")
shell.setAlias("grep", "grep --color")
os.setenv("EDITOR", "/bin/edit")
os.setenv("HISTSIZE", "10")
os.setenv("HOME", "/home")
os.setenv("IFS", " ")
os.setenv("MANPATH", "/usr/man:.")
os.setenv("PAGER", "/bin/more")
os.setenv("PS1", "$HOSTNAME$HOSTNAME_SEPARATOR$PWD # ")
os.setenv("LS_COLORS", "{FILE=0xFFFFFF,DIR=0x66CCFF,LINK=0xFFAA00,['*.lua']=0x00FF00}")
shell.setWorkingDirectory(os.getenv("HOME"))
local home_shrc = shell.resolve(".shrc")
if fs.exists(home_shrc) then
loadfile(shell.resolve("source", "lua"))(home_shrc, "-q")
end

View File

@ -1,5 +0,0 @@
alias l="ls -lhp"
alias ..="cd .."
alias df="df -h"
alias grep="grep --color"

View File

@ -1,7 +1,7 @@
-- called from /init.lua
local raw_loadfile = ...
_G._OSVERSION = "OpenOS 1.6.5"
_G._OSVERSION = "OpenOS 1.6.6"
local component = component
local computer = computer

View File

@ -253,7 +253,7 @@ local function display(names)
max_size_width = math.max(max_size_width, formatSize(info.size):len())
max_date_width = math.max(max_date_width, formatDate(info.time):len())
end
mt.__index = function(tbl, index)
mt.__index = function(_, index)
local info = stat(names, index)
local file_type = info.isLink and 'l' or info.isDir and 'd' or 'f'
local link_target = info.isLink and string.format(" -> %s", info.link:gsub("/+$", "") .. (info.isDir and "/" or "")) or ""
@ -267,7 +267,7 @@ local function display(names)
end
elseif ops["1"] or not fOut then
lines.n = #names
mt.__index = function(tbl, index)
mt.__index = function(_, index)
local info = stat(names, index)
return {{color = colorize(info), name = info.name}}
end
@ -302,10 +302,10 @@ local function display(names)
end
end
lines.n = items_per_column
mt.__index=function(tbl, line_index)
mt.__index=function(_, line_index)
return setmetatable({},{
__len=function()return num_columns end,
__index=function(tbl, column_index)
__index=function(_, column_index)
local ri = real(column_index, line_index)
if not ri then return end
local info = stat(names, ri)

View File

@ -18,11 +18,11 @@ function shell.getShell()
if shells[shellName] then
return shells[shellName]
end
local sh, reason = loadfile(shellName)
local sh, load_reason = loadfile(shellName)
if sh then
shells[shellName] = sh
end
return sh, reason
return sh, load_reason
end
-------------------------------------------------------------------------------

View File

@ -22,7 +22,7 @@ Many component methods have a short documentation - use `=component.componentNam
You can get a list of all attached components using the `components` program.
If you encounter out of memory errors, throw more RAM at your computer.
Have you tried turning it off and on again?
To disable this greeting, install OpenOS to a writeable medium and remove the `/etc/motd` line from `/etc/profile`.
To disable this greeting, install OpenOS to a writeable medium and remove the `/etc/motd` line from `/etc/profile.lua`.
Did you know OpenComputers has a forum? No? Well, it's at https://oc.cil.li/.
Please report bugs on the Github issue tracker, thank you!
Beware of cycles when building networks, or you may get duplicate messages!