group the old and new ideas into misc

typed (file) still needs work, but at least the typed directory is gone
This commit is contained in:
Torsten Ruger 2018-04-11 20:53:49 +03:00
parent 4dcfddb270
commit a42ca6e514
12 changed files with 80 additions and 91 deletions

View File

@ -16,9 +16,9 @@
%ul.nav
%li= link_to "Home" , root_path
%li= link_to "Architecture", "/rubyx/layers.html"
%li= link_to "Soml (obsolete)" , "/soml/typed.html"
%li= link_to "Arm Resources" , "/arm/overview.html"
%li= link_to "About" , "/project/motivation.html"
%li= link_to "Misc" , "/misc/index.html"
%li= link_to "News" , blog_index_path
=link_to "https://github.com/ruby-x" do
=image_tag "x-small.png", style: "position: absolute; top: 15px; right: 15px; border: 0; width: 70px"

View File

@ -0,0 +1,5 @@
.row
%ul.nav
%li= link_to "Threads (rumble)" , "threads.html"
%li= link_to "Optimisation (ideas)" , "optimisations.html"
%li= link_to "SOML (old)", "soml.html"

View File

@ -0,0 +1,12 @@
= render "pages/misc/menu"
%h1= title "Ideas, old and new"
An idea is where everything starts. Like this project. But not every idea
makes it to reality, and some that do do not turn out as planned.
This is a collection of both, the overripe and unripe. Maybe we can learn from the
first, and by continuously reexamining the second see if it is worth the
effort to bring them down to earth.
%h2 Unrealized

View File

@ -0,0 +1,33 @@
= render "pages/misc/menu"
%h1=title "Optimisation ideas"
%p I wont manage to implement all of these idea in the beginning, so i just jot them down.
%h3 Inlining
%p
Ok, this may not need too much explanation. Just work. It may be interesting to experiment how much this saves, and how much
inlining is useful. I could imagine at some point its the register shuffling that determines the effort, not the
actual call.
%p Again the key is the update notifications when some of the inlined functions have changed.
%p
And it is important to code the functions so that they have a single exit point, otherwise it gets messy. Up to now this
was quite simple, but then blocks and exceptions are undone.
%h3 Register negotiation
%p
This is a little less baked, but it comes from the same idea as inlining. As calling functions is a lot of register
shuffling, we could try to avoid some of that.
%p More precisely, usually calling conventions have registers in which arguments are passed. And to call an “unknown”, ie any function, some kind of convention is neccessary.
%p
But on “cached” functions, where the function is know, it is possible to do something else. And since we have the source
of the function around, we can do things previously impossible.
%p One such thing may be to recompile the function to accept arguments exactly where they are in the calling function. Well, now that its written down. it does sound a lot like inlining, except without the inlining:-)
%p
An expansion if this idea would be to have a Negotiator on every function call. Meaning that the calling function would not
do any shuffling, but instead call a Negotiator, and the Negotiator does the shuffling and calling of the function.
This only really makes sense if the register shuffling information is encoded in the Negotiator object (and does not have
to be passed).
%p
Negotiators could do some counting and do the recompiling when it seems worth it. The Negotiator would remove itself from
the chain and connect called and new receiver directly. How much is in this i couldnt say though.

View File

@ -1,7 +1,27 @@
= render "pages/soml/menu"
= render "pages/misc/menu"
%h1= title "Soml Syntax"
Soml was a step on the way. While i was still thinking about VM's and c++ ,
the year was 2015.
%br
I had thought that some kind of typed layer was needed, and that one could
implement the higher level in a language. A typed language, sort of like c++,
that would be used to implement the code of ruby.
%br
A little like PyPy has a core that only uses a small set of python, that can,
a la crystal, be fully type inferred.
%br
This idea turned out to be wrong, or difficult. Because the bridge between the
typed an untyped was unclear or i didn't get it to work. The current system
works by typing self, but not it's instances. A difficult mix to express in a
language.
%br
This led me to abandon soml and rewrite the functionality as vool and mom layers.
But Soml was working, the parser is still about and there are some interesting
=link_to "benchmarks" , "soml_benchmarks.html"
that came from it and really validated the calling convention.
%h2 Top level Class and methods
%p The top level declarations in a file may only be class definitions
%pre

View File

@ -1,7 +1,11 @@
= render "pages/soml/menu"
= render "pages/misc/menu"
Disclaimer: read the intro of
=link_to "Soml" , "soml.html"
first. This is obsolete, and has only historic value.
%h1= title "Simple soml performance numbers"
%p
These benchmarks were made to establish places for optimizations. This early on it is clear that
performance is not outstanding, but still there were some surprises.

View File

@ -1,4 +1,4 @@
= render "pages/rubyx/menu"
= render "pages/misc/menu"
%h1= title "Threads are broken"

View File

@ -1,4 +1,4 @@
= render "pages/soml/menu"
= render "pages/misc/menu"
%h1= title "Typed intermediate representation"

View File

@ -4,5 +4,3 @@
%li= link_to "Parfait", "parfait.html"
%li= link_to "Debugger", "debugger.html"
%li= link_to "Memory" , "memory.html"
%li= link_to "Threads" , "threads.html"
%li= link_to "Optimisation ideas" , "optimisations.html"

View File

@ -1,75 +0,0 @@
= render "pages/rubyx/menu"
%h1=title "Optimisation ideas"
%p I wont manage to implement all of these idea in the beginning, so i just jot them down.
%h3#avoid-dynamic-lookup Avoid dynamic lookup
%p This off course is a broad topic, which may be seen under the topic of caching. Slightly wrongly though in my view, as avoiding them is really the aim. Especially for variables.
%h4#i---instance-variables I - Instance Variables
%p Ruby has dynamic instance variables, meaning you can add a new one at any time. This is as it should be.
%p
But this can easily lead to a dictionary/hash type of implementation. As variable “lookup” is probably
%em the
most
common thing an OO system does, that leads to bad performance (unneccessarily).
%p
So instead we keep variables layed out c++ style, continous, array style, at the address of the object. Then we have
to manage that in a dynamic manner. This (as i mentioned
= succeed ")" do
%a{:href => "memory.html"} here
%p
When a new variable is added, we create a
%em new
Type and change the Type of the object. We can do this as the Type will
determine the Class of the object, which stays the same. The memory page mentions how this works with constant sized objects.
%p So, Problem one fixed: instance variable access at O(1)
%h4#ii---method-lookup II - Method lookup
%p Off course that helps with Method access. All Methods are at the end variables on some (class) object. But as we cant very well have the same (continuous) index for a given method name on all classes, it has to be looked up. Or does it?
%p
Well, yes it does, but maybe not more than once: We can conceivably store the result, except off course not in a dynamic
structure as that would defeat the purpose.
%p
In fact there could be several caching strategies, possibly for different use cases, possibly determined by actual run-time
measurements, but for now I just destribe a simeple one using Data-Blocks, Plocks.
%p
So at a call-site, we know the name of the function we want to call, and the object we want to call it on, and so have to
find the actual function object, and by that the actual call address. In abstract terms we want to create a switch with
3 cases and a default.
%p
So the code is something like, if first cache hit, call first cache , .. times three and if not do the dynamic lookup.
The Plock can store those cache hits inside the code. So then we “just” need to get the cache loaded.
%p Initializing the cached values is by normal lazy initialization. Ie we check for nil and if so we do the dynamic lookup, and store the result.
%p
Remember, we cache Type against function address. Since Types never change, were done. We could (as hinted above)
do things with counters or robins, but that is for later.
%p
Alas: While Types are constant, darn the ruby, method implementations can actually change! And while it is tempting to
just create a new Type for that too, that would mean going through existing objects and changing the Type, nischt gut.
So we need change notifications, so when we cache, we must register a change listener and update the generated function,
or at least nullify it.
%h3#inlining Inlining
%p
Ok, this may not need too much explanation. Just work. It may be intersting to experiment how much this saves, and how much
inlining is useful. I could imagine at some point its the register shuffling that determines the effort, not the
actual call.
%p Again the key is the update notifications when some of the inlined functions have changed.
%p
And it is important to code the functions so that they have a single exit point, otherwise it gets messy. Up to now this
was quite simple, but then blocks and exceptions are undone.
%h3#register-negotiation Register negotiation
%p
This is a little less baked, but it comes from the same idea as inlining. As calling functions is a lot of register
shuffling, we could try to avoid some of that.
%p More precisely, usually calling conventions have registers in which arguments are passed. And to call an “unknown”, ie any function, some kind of convention is neccessary.
%p
But on “cached” functions, where the function is know, it is possible to do something else. And since we have the source
(ast) of the function around, we can do things previouly imposible.
%p One such thing may be to recompile the function to acccept arguments exactly where they are in the calling function. Well, now that its written down. it does sound a lot like inlining, except without the inlining:-)
%p
An expansion if this idea would be to have a Negotiator on every function call. Meaning that the calling function would not
do any shuffling, but instead call a Negotiator, and the Negotiator does the shuffling and calling of the function.
This only really makes sense if the register shuffling information is encoded in the Negotiator object (and does not have
to be passed).
%p
Negotiators could do some counting and do the recompiling when it seems worth it. The Negotiator would remove itself from
the chain and connect called and new receiver directly. How much is in this i couldnt say though.

View File

@ -1,8 +0,0 @@
.row
%ul.nav
%li
%a{:href => "typed.html"} Typed
%li
%a{:href => "benchmarks.html"} Performance
%li
%a{:href => "syntax.html"} Syntax (obsolete)