Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Brian Shirai
@brixen
so a combination of compile-time raise option and run-time rescue option could make this quite workable
   --log-concurrent-update    Log when T2 updates an object created by T1
   --raise-concurrent-update  Raise a RuntimeError when T2 updates an object created by T1
Brian Shirai
@brixen
@chuckremes just pushed that code
I'll add some niceties probably tomorrow
since I have the MemoryVisitor now, I need to implement become as well, which will make programming proxies really nice :grinning:
another thing we can do with MemoryVisitor is search a subgraph of the object graph, say from an explicit set of 1+ "roots" instead of the graph roots
I should expose some nice methods for that in Rubinius::Memory
Chuck Remes
@chuckremes
those are treats!
will play with them soon
Brian Shirai
@brixen
gotta figure out what's happening with the rubinius log file lock deadlock
Brian Shirai
@brixen
@chuckremes I’ve made it through my list above pretty quickly, and while I’ve got more to do on the GC (including tracking down nokogiri issue), I’m curious what would be the next most useful thing for you?
Brian Shirai
@brixen
thinking about the JIT, here are some things that are important:
  1. I want to respect "do a little, get a little; do a lot, get a lot";
  2. by using functions as the interface between nanopasses, we can leverage f: A -> B, g: B -> C for composition of passes;
  3. we need an explicit mechanism for describing dependencies independent of the function composition;
  4. then 2 and 3 give us the ability to parallelize compilation where dependencies for pass B(i) are met by an B(i-n), n >= 1
I wish it was easy to do subscript
Brian Shirai
@brixen
the "do a little, get a little" is really important because the old JIT was "do a lot, get a little" and deterred people from contributing
Brian Shirai
@brixen
@chuckremes ok, you need to configure with --{log, raise}-concurrent-update and then you can run rbx with -Xmachine.concurrent.update.{log, raise}=true
I need to make one more change to set the thread_id of the Thread and not Fiber into the object header
since all Fibers attached to a Thread should be able to update an object created by anything on that Thread
Chuck Remes
@chuckremes
@brixen let me just recap what i think i’ve got now in rbx
  1. a logging facility that will tell me when there is cross-thread access (or just mutation?)
  1. the ability for the aforementioned logging facility to raise on cross-thread access (mutation?)
  1. better GC
question: are the isolated heaps implemented yet or just this logging mechanism? if implemented, are they exposed to Ruby-land so I can say Thread.new(heap: :isolated) or Thread.new(heap: :shared) or something?
back to your question… i have a long wish-list but i think i need to subordinate my desires now for something that this community needs which is a taste of the JIT
we want to entice some folks back into the fold but pretty much everyone runs for the hills when they see the current performance levels; if you could spike out a few nanopasses and get some inlining or peephole optimization or onstack replacement or whatever working to boost regular perf then that would be great
Chuck Remes
@chuckremes
so that’s number 1 on my list now :)
Brian Shirai
@brixen
@chuckremes the log or raise on concurrent update is only mutation across threads, and I don't have a mechanism yet to transfer ownership, but that isn't much work, I'll add it
there are a lot of improvements to the GC, more to do
isolated heaps are not yet in, I'll add back thread-local allocation first, and then the ability to create isolated heaps
the isolated heaps need something like "main()", which will be a function, and they won't be able to use Ruby classes unless I come up with a reasonable method to inject those references
the "closed" heaps, which all pointers out of the heap, but not into the heap, can use Ruby classes
I hear you on the JIT, I'm on the same page, so I'll get some basic functions in, and then spike some JIT functionality
Chuck Remes
@chuckremes
great!
Brian Shirai
@brixen
so, this hang is really nasty because the lock being waited on is ultimately in the clib :sob:
a call to localtime_r is calling tzsetwall_basic and that's trying to aquire a lock that is not held in this process
the only thing I can think of is that the lock is held in the parent before fork()
which means that we're racing the logger when forking, but I can't figure out how
Brian Shirai
@brixen
interesting, it looks like MemoryVisitor and MemoryTracer will possibly converge
I may be able to implement thread-local allocator, but really want to get Object#become in place
Brian Shirai
@brixen
hmm, that deadlock issue could be as simple as explicitly holding the logger lock on fork and immediately releasing it in the child to ensure it's in a known state
Brian Shirai
@brixen
@chuckremes I have another treat, but it's not fully baked yet
describe "Object#become" do
  it "replaces the receiver with the argument bidirectionally" do
    a, b = "me", "you"

    a.should eql("me")
    b.should eql("you")

    a.become b

    a.should eql("you")
    b.should eql("me")
  end
end
:laughing:
Object#become may seem whimsical, but it's not because the same mechanism must work to implement evacuation / compaction in the heap
right now, it's not working for object instance variables, for example
this can also be a useful mechanism for injecting a reference into an "isolated" heap
Brian Shirai
@brixen
Chuck Remes
@chuckremes
i always liked the concept of become because it made the State Pattern so clear… as you transition from state to state, the object becomes an instance of the next state. such a cool idea.
Chuck Remes
@chuckremes
ah, a link to gilad bracha! i used to follow him way back when it seemed like he might actually ship Newspeak
never happened :)