Skip to content

Add lazy initialization (and explicit finailization) to mrbgems.#1844

Closed
monaka wants to merge 1 commit into
mruby:masterfrom
monaka:pr-lazy-initialization-support
Closed

Add lazy initialization (and explicit finailization) to mrbgems.#1844
monaka wants to merge 1 commit into
mruby:masterfrom
monaka:pr-lazy-initialization-support

Conversation

@monaka
Copy link
Copy Markdown
Contributor

@monaka monaka commented Mar 10, 2014

No description provided.

@mattn
Copy link
Copy Markdown
Contributor

mattn commented Mar 11, 2014

The name mrb_require_prelinked is bits potentially confusable.

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

What name is better? mrb_require_static() or something?
My future plan is to implement mrb_require() that dispatches mrb_require_prelinked() and mrb_require_dynamiclink().

@bjorndm
Copy link
Copy Markdown

bjorndm commented Mar 11, 2014

How about mrb_lazy_initialize() and mrb_lazy_finalize() ? On a side note, wouln't it be more convenient if gems could specify their requirements (in terms of other gems), and be loaded in the correct order?

@matz
Copy link
Copy Markdown
Member

matz commented Mar 11, 2014

First of all, mrbgems already have dependency info that can generate ordered initialization by topological sort (tsort). I think half of the solution provided by this pull-request is unnecessary and too primitive.

I am not sure how much the other half is important. Could you explain use-case?

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

The typical situation is handling extendable target boards.
Some extend devices may be disconnected on boot time.
I see we can initialize gems (and classes) and let them return errors until a extend device connected.
But it's more intuitive that such gems are initialized on connected time.

And I think gem's initialize (and finalize) order is not always same as gem's dependency tree.

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

The another use case is to run multiple applications on same VM.
On the current version, all mrb_state must share same gems.

@matz
Copy link
Copy Markdown
Member

matz commented Mar 11, 2014

You said "it's intuitive to initialize such device on connection", but at least from my point of view, initializing classes and modules in the middle of execution is an anti-pattern. In CRuby, autoload may cause such situation, but I saw more troubles than benefits. Rather initializing classes and modules from mrb_open() then initializing the device when the first instance is allocated, will cause less problems. I am not that positive to support anti-pattern.

And you mentioned cases that sought initialization order is different from dependency order. I understand there can be theoretical possibility, but I don't see any concrete ones.

Last of all, having different mrbgems set for different VM is bit theoretical. And even if we want to address that problem, I believe there must be better API and implementation.


(Japanese Version)

まず、「接続時の初期化が自然」と言われましたが、実行時にクラスが増えたり減ったりするのはアンチパターンです。autoloadなどでそのようなことが発生しますが、利点より問題のほうが多いです。むしろ、通常のクラス定義などはmrb_open()から行い、実際に機能を使う時、たとえば最初のオブジェクトを生成する時にデバイスの初期化を行うほうが自然かつ問題が少ないと考えます。アンチパターンを積極的に支援する機能を追加することには消極的です。

次に、仮に初期化したい順序が依存順序と異なるケースがありえるということですが、具体的なケースを見ないとなんとも言えません。理論的な可能性はわかりますが、具体的にどのくらい頻繁に起きるケースでどのくらい困るのかわからないと。

最後にVM毎に異なるmrbgemsを持たせることができない点ですが、これも理論上の危険性で、これで困ることはごく少ないように思われますし、仮にこれに対処するにしてもそれならもっと良いAPIと実装がありそうな気がします。

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

I see the point of view. But just one more.

It is not theoretical that having different mrbgems set.
It may be strongly required by environments that have 1-process-n-thread model.
Some types of realtime kernel (OSEK, ITRON, eCOS, and more) and cloud OSes are typical.
Especially mission critical systems have an antipathy to load un-required code on memory.
I wish better API and implementation as you say.

@monaka monaka closed this Mar 11, 2014
@kyab
Copy link
Copy Markdown
Contributor

kyab commented Mar 11, 2014

Using minimum mrbgems in build_config.rb, then call mruby-require on each mrb_state is not enough?

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

@kyab Not always target systems have filesystems. ;-)

@kyab
Copy link
Copy Markdown
Contributor

kyab commented Mar 11, 2014

Oh I see. But If mrbgem is ruby-only , its quite easy to load contents of .mrb, or contents of C-dumped(.c) into only specific mrb_state.

If your mrbgem is written by C, anyway code will be shared with threads in one-process model.
If it is not acceptable, maybe it means you should have multi-process(separate memory space)system, or filesystem.

@bovi
Copy link
Copy Markdown
Member

bovi commented Mar 11, 2014

I have implemented the dependency order some time ago and I would like to know a situation where the dependency resolving has an unexpected behavior.

Addition my proposal for lazy loading would be to introduce two new c functions:

  • function 1 inits mruby without any mrbgems
  • function 2 inits mrbgems on a running mruby instance

This is very clean to implement and should solve the situation of a to early initialization.

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 11, 2014

@kyab
On the viewpoint of mruby script, the application cannot access related C code until a mrbgem was loaded. I agree it's not protected for C code. But it's a kind of protection for mruby script.
Possibly some mrbgem is used for interface for system layer.
We can't get the merit around the protection when we run all applications with all gems.

(Japanese)
mrubyスクリプトから見ると,mrbgemに紐付いたCコードは,そのmrbgemがロードされるまで触れませんよね.これがC言語から見て何の保護にもならないのは同意です.でも,mruby スクリプトに対しての保護にはなっているわけです.
全てのアプリケーションで同じgemsを動かしているかぎり,この保護が得られません.

@mattn
Copy link
Copy Markdown
Contributor

mattn commented Mar 11, 2014

Last of all, having different mrbgems set for different VM is bit theoretical. And even if we want to address that problem, I believe there must be better API and implementation.

This is one of the counter-example.

https://github.com/mattn/mruby-sandbox

mruby-sandbox need to initialize safety-mrbgems.

@matz
Copy link
Copy Markdown
Member

matz commented Mar 12, 2014

I have no RTOS experience but if having unrelated functions in memory should be avoided at high priority, why on earth they use thread (shared memory model) and mruby (rich set of predefined functions)? It seems contradiction to me to use mruby for the first hand.

On the other hand, mruby-sandbox is a good example of having different gems set for multiple mrb_states. I'd love to add API to support such use-case.

@bjorndm
Copy link
Copy Markdown

bjorndm commented Mar 12, 2014

@matz, let me explain a bit on why we would use (m)ruby for safety related applications.
I have some experience with using Ruby in a safety-related environment, railway applications to be more precise . So I know what's important and what is less important when complying to safety standards.

Thanks to the Ruby ISO standard, it's now possible to use (m)ruby, for such safety related programs. Since Ruby is garbage colected, and has no pointers, it has some advantages over using, say, C or C++ in this context. Furthermore, mruby can be compiled to byte code, which prevents modificationof the program at run time, another bonus over using plain ruby for safety related applications.

I think that for most safety standards, loading "unused" code may be a small problem, but not a serious one. In the implementation process required by thesafety standards, this can be justified by stating in the required safety documents that these modules of mruby are part of the programming language's run time library as is required by the Ruby ISO standard.

Far more important for safety application is that there are good unit tests and integration tests to prove that the (m)ruby implementation is safe to use. Another important thing is that we should adhere to a C and Ruby code standard. For the time being, these two standards are not written out explicitly in the mruby project... Perhaps I should contribute those if they seem valuable, but that is a different issue...

Back on topic,I also like the idea of a sandbox. This is useful bothin safety-related programs and in game scripting.

@bovi
Copy link
Copy Markdown
Member

bovi commented Mar 12, 2014

@bjorndm a little bit off-topic: We are working apparently in the same environment. Just out of my curiosity, are you really talking here about using Ruby in application which require > SIL2? If yes can you disclose some information on which continent you are active and if you have already projects running with a >SIL2 validated Ruby application?

@bjorndm
Copy link
Copy Markdown

bjorndm commented Mar 12, 2014

@bovi, yes, we are planning to use a supporting ruby (web)application in a SIL3 environent. However, we were able to reduce the requirements for the ruby application itself to SIL 0. Still, the fact that ruby has an ISO standard and plenty of unit tests has been a great help. This actually makes Ruby the /only/ programming language commonly used for web applications that is standardized and testable. There's no standard for Java, PHP, Python, Lua... and often they lack unit tests. So, it's much harder to jusify the useof those languages for any SIL level, really. I'm active in Europe and we follow the european railway norms. Contact me though other means (like an issue on one of my repos) to discuss this more, if you like.

@matz matz reopened this Mar 12, 2014
@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 13, 2014

@matz There are some requirement levels. "SIL" is a one of indicators.
It's possible some applications want reduce the machine language instruction set. (Really available. One example is motor controller for hybrid cars.)
And also some may be no care if they use CRuby (more rich set). There is no contradiction.
Though in general, they don't like unused function in memory. Because it increases the test cost.
Seems not only embedded systems. But they are especially sensitive.

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 13, 2014

Anyway. I see @matz don't accept this PR. I'll re-implement this in an another way (maybe extension to mruby-require, or something).
I close this PR.

@monaka monaka closed this Mar 13, 2014
@kyab
Copy link
Copy Markdown
Contributor

kyab commented Mar 13, 2014

#1852 is insufficient? I wonder mrb_init_mrbgem(mrb,name) (instead of single mrb_init_mrbgems(mrb)) solve someone's problem.

@monaka
Copy link
Copy Markdown
Contributor Author

monaka commented Mar 13, 2014

As there are so many cases around initialization and finalization, I have no objection about #1852.
But I prefer mruby-sandbox approach to mrb_init_mrbgem(mrb, name). Even though they are almost same.

take-cheeze added a commit to take-cheeze/mruby that referenced this pull request May 8, 2014
`mrb_final_mrbgems` will be called as mrb_state atexit function.
Maybe useful in mruby#1844.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants