Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nice job #1

Closed
SoonyangZhang opened this issue Apr 7, 2020 · 8 comments
Closed

nice job #1

SoonyangZhang opened this issue Apr 7, 2020 · 8 comments

Comments

@SoonyangZhang
Copy link

I just read a project which is also quite nice. https://github.com/YingshuLu/libcask.

@cuu
Copy link

cuu commented Apr 7, 2020

赞,这个东西放到lisp中的话就可以让lisp起飞了

@navytux
Copy link

navytux commented Apr 13, 2020

Thanks, interesting work.

The 10x slowness on Go side seems to be related to the way how Go handles many many semaphores simultaneously golang/go#38420. Hopefully it could be fixed.

The idea to use compiler plugin to statically determine function frame size is interesting. Unfortunately it cannot be generally used due to a) recursion, and b) calling functions by indirection (pointers, interfaces, etc), so some kind of runtime stack guarding will still have to be used to avoid corrupting memory.

The channel API misses select. Some related links on CSP topic for C/C++/Cython and Python: libgolang, pygolang.

@shiyanhui
Copy link
Owner

shiyanhui commented May 2, 2020

@navytux

  • For function pointers, you can set the stack size manually by option extra-su-file of cspcli.
  • For select, there is no need to implement one. See the select example.

@navytux
Copy link

navytux commented May 3, 2020

@shiyanhui, thanks for feedback.

  • One can indeed set stack size manually, but my point is that it is relatively hard to correctly estimate needed stack size by hand and if that estimation is wrong it will result in memory corruption on stack overflow. That's what I was meaning with "some kind of runtime stack guarding will still have to be used to avoid corrupting memory" above.
  • The select implementation you just added in 28711589 has the same drawback as e.g. goless has - it does not correctly handle select - select interactions which are frequently used in Go. Please see through which hoops libgolang has to go to provide working select: https://lab.nexedi.com/nexedi/pygolang/blob/814d8b86/golang/runtime/libgolang.cpp#L854-1186 and it is much more compared to a straight busy-wait loop with polling.

Kirill

@shiyanhui
Copy link
Owner

Hi @navytux ,

  • It's very difficult to compute the precise stack size of a function which is recursive or calls pointer functions in compile time, so cspcli provides --extra-su-file and --default-stack-size for this. It's true that "it is relatively hard to correctly estimate needed stack size by hand", but I think a not that correct stack size is also acceptable and practical.

  • This commit is not an implementation of select, it's just an example of select simulation using libcsp. There is no select implementation in libcsp and I do think there is need to implement it. Libcsp can handle the issue you pointed out correctly. See the full example.

Thanks.

@navytux
Copy link

navytux commented May 3, 2020

Hi @shiyanhui,

  • My point is that it will be memory corruption if manual stack size estimate is not right. Memory corruption usually results in arbitrary hard to diagnose breakage, (a lot of) developers time to debug, grey hair and things like that. That's why I said that it needs "some kind of runtime stack guarding" to protect people from the above scenario. The simplest runtime stack guard is via adding additional page to the end of the stack to catch access on stack overflow. The other known possibility is to use support from compiler with something like -fsplit-stack. Other options might exist. I think in 2020 we all should realize that lack of safety and protection, even though it allows proof-of-concept to be done quickly and run fast, is significant hidden cost.

  • I think there is something not completely right with your second select example: If I change it as follows:

--- a/select2.c.kirr
+++ b/select2.c
@@ -45,7 +45,8 @@
    chan_t(int) *chn2 = chan_new(int)(0);
    chan_t(int) *chn3 = chan_new(int)(0);
 
-   async(select1(chn, chn2); select2(chn, chn3));
+   //async(select1(chn, chn2); select2(chn, chn3));
+   async(select2(chn, chn3));
    hangup(timer_second);
    
    chan_destroy(chn);

Here is what I get as its output:

libcsp/examples$ make EXAMPLE=select2
./select2
Written 1 to main channel
# pause of 1 second and then exit
# `Received 1 from main channel` is _not_ printed

So it means that write to chn done by select2() routine succeeds without anyone reading from chn. Is it the semantics that synchronous (= unbuffered) Go channels are expected to provide?

Kirill

@shiyanhui
Copy link
Owner

The channel in libcsp is always buffered which is different with chan of golang. There is no the unbuffered concept. chan_new(int)(0) means the length of the channel is 2^0, i.e 1. So it will not block. The behavior in your modified code is expected.

@navytux
Copy link

navytux commented May 3, 2020

I see, thanks for feedback. I can only add that in my view synchronous Go channels are the most useful. They also bring the most of complexity into implementation of send/recv and select.

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

No branches or pull requests

4 participants