On 3 May 2015 at 05:52, Luke Gorrie <
lu...@snabb.co> wrote:
> Cool :).
>
> I wonder if there is also a good way that we could shorten the names of apps
> (e.g. from 'apps.basic.sink' to 'sink') without introducing problems with
> ambiguity.
i'm using `package.path` to search for the app file. we could add
some app-specific directory entry, like `package.path =
packate.path..';aps/.?.lua'
> I have not dug into the implementation yet but I like the direction the
> interface is going! I suspect that the implementation will grow more
> constraints if it wants to allow separate Lua states and parallel execution
> of apps.
i did stumble into a few sandbox "leaks", i.e differences between the
current implementation and what could be assumed on a many-state
world. for example, `package.loaded` is the same table for everybody,
so `require()`d modules are loaded once, instead of once per app.
I think a many-state implementation would be interesting to see, even
if there's no parallel execution yet.
> Having a separate file for each app does seem pretty okay to me, even for
> this extreme case of the app only being around 5 lines of code.
i like that too. i mentioned it because it becomes a requirement, not
only nice code layout.
> The relink() method should perhaps be rethought in general...
i think it can be very useful to have a callback at this point. maybe
the `relink()` name is too specific, something like `post_setup()`
could be more readable.
> These apps simply want a quick way to iterate over their input ports,
> without caring what they are called. This would "just work" if the link
> tables ('input' and 'output') indexed the links both by name (input.x and
> input.y) and by number (input[1] and input[2]). This could be taken care of
> in the engine and then the basic apps wouldn't need to relink().
>
> Having said that, we currently have too little verification of the links in
> the app network. We should print good warning/error messages if you forget
> to connect a required link of an app or if you connect the same link more
> than once. This should be fixed in some nice way, perhaps partly in the
> engine and partly in the apps. (Likewise for invalid app configurations.)
something like this?:
----- implementation -----
local function fields_present(table, f, ...)
if f == nil then return true end
if t[f] == nil then return false, f end
return fields_present(table, ...)
end
function required_inputs(...)
local ret, missing = fields_present(input, ...)
assert(ret, 'missing required input '..missing)
end
function required_outputs(...)
local ret, missing = fields_present(output, ...)
assert(ret, 'missing required output '..missing)
end
-----------------
--- usage (in tunnel.lua) -----
required_inputs('encapsulated', 'decapsulated')
required_outputs('encapsulated', 'decapsulated')
------
> I would prefer to see an old-fashioned require() than a new-fangled
> include() for sharing common code. Otherwise the reader has to digress and
> read what include() does before they can understand the file.
>
> Can we solve this in a nice way without adding the new programming
> construct?
it's not so easy, the semantics are just too different.
first i tried a new option to be used instead of `package.seeall` to
make the submodule environment the same as the calling app. it was
quickly a hideous mess of `gefvenv()` and metatables. in the end the
shared `package.loaded` meant the submodule was executed only once, so
it couldn't add itself to each calling app.
giving each app it's own copy of `package.loaded` was complex and
fragile. i think this might have to wait until we have multiple Lua
states.
then i tried a "spill()" function, to copy submodule-defined variables
into the app environment. that seemed to work for a while, but the
pulled functions didn't have access to the app's "global" variables,
so i had to add those as arguments to the submodule, making it
not-so-standard `require()`, and so much boilerplate that it negated
most of the benefits of the sandbox.
> If the problem is that we are requiring apps to implement too many callbacks
> then perhaps we could try to reduce those instead e.g. remove the relink()
> callback entirely in this instance so that there is no pressure on reusing
> callback/method implementations.
i think currently there's very few presure on reusing implementations;
just that it might be a good tool to use, and having `import()`
available (or a clever use of `require()`) would reduce requests for
inheritance.
> Question: where, really, does this difference come from? Is it from the FFI
> metatables on link/packet objects, or from the app instance having a private
> 'local' environment instead of using "instance variables", or from both of
> those things, or from neither but instead something else that we are
> overlooking? (This is not to say that we need to dissect it in massive
> detail but just to confident that it is indeed strongly related to the basic
> programming style.)
I did a few tests switching some lines of tunnel.lua back and forth
between the original and the modified one, checking performance at
each step.
tonight, it seems using locals vs globals for the instance variables
have very little, if any, impact.
the most significant change seems to be `p:prepend(header,
HEADER_SIZE)` vs. `packet.prepend(p, header, HEADER_SIZE)`, in the
encapsulation path.
the `link.receive(...)` lines would have a similar impact, but they
were already cached because of the `local receive, transmit =
link.receive, link.transmit` common at the top of the file.
so, the conclusion seems to be not that OOP syntax is "better" than
manually cacheing, but that it's less likely to miss one or two
significant points.
now it gets interesting to see if converting freelist.lua to this
style would make it better...
--
Javier