Re: [MacRuby-devel] book idea - making it look like Ruby

2011-02-18 Thread Charles Oliver Nutter
On Fri, Feb 11, 2011 at 4:08 PM, Rich Morin r...@cfcl.com wrote:
 At 6:09 PM -0200 2/11/11, Caio Chassot wrote:
 On 2011-02-11, at 15:25 , Matt Aimonetti wrote:

 Magically converting a snake_case method call to a
 CamelCase method dispatch is bad for peformance
 and documentation.

 It's not clear to me that there would be a significant
 performance impact.  It might be possible to do (most
 of) the translations at start-up time, avoiding much
 impact during execution.

In JRuby it currently has no performance impact. The camel_cased
versions are defined as aliases to the original. I forget whether we
define them as traditional aliases (wrapped by another structure) or
if we just bind the same method object under all names.

We have also debated making the aliases *redispatch* so that if you
wanted to replace them all you'd just replace the original camelCased
version. That turned out to be a perf issue in practice, so we backed
it off until we can come up with a nice way to have multiple names
resolve to the same method object.

FWIW, JRuby users would go ape if we took away snake_cased versions of
Java names. They love having everything look like Ruby, and I
personally think it helps the code flow a lot more naturally to have a
single style...not to mention you don't have to remember whether
you're calling a snake_cased or camelCased method...you just always
use snake_case.

 The question of documentation is also somewhat iffy.
 There is already a difference in appearance between
 the ObjC and MacRuby calling syntaxes.  Would merely
 allowing (ie, not requiring) the use of snake_case
 make this much problem much worse?

As far as I know, there's never been any confusion about snake_cased
aliases in JRuby. People read the JavaDocs, mentally switch to
snake_case, and proceed.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] WeakRef advice

2011-02-18 Thread Charles Oliver Nutter
Another important use of weakrefs came to mind: avoiding finalization.

In general, finalizers are a bad idea. They often block GC, or at
least block each other. They add overhead to GC cycles, since either
finalizers must be run or objects must be enqueued for another thread
to run their finalizers. By using WeakReferences (and especially
PhantomReferences) you can drive finalization from userland code,
avoiding much of the GC overhead that might otherwise result.

- Charlie

On Fri, Feb 18, 2011 at 5:28 PM, Charles Oliver Nutter
head...@headius.com wrote:
 On Tue, Feb 15, 2011 at 5:28 PM, Laurent Sansonetti
 lsansone...@apple.com wrote:
 Hi Alan,
 Do you control the data structure that holds a reference to 'B'? If yes, you
 may want to use NSHashTable which supports weak references.
 To me, this sounds like a design problem. Maybe your project can be
 re-architectured to avoid this pattern.

 Weak references and weak lists/hashes are often very useful for caches
 you need to age out or when you need to associate data with a given
 instance of an object without holding hard references. Using weak
 references is definitely not a design problem in itself.

 I'm also disappointed that you'd recommend people use NSHashTable
 rather than just fixing WeakRef :) In JRuby, we nuked weakref.rb some
 time ago because it has a lot of problems. Instead, we wrap the JVM's
 builtin weakrefs.

 See also the weakling gem, which (for JRuby) provides additional
 features mentioned in that Ruby redmine ticket like reference queues
 and a simple weak ID hash to use in place of _id2ref.

 - Charlie

___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] WeakRef advice

2011-02-18 Thread Charles Oliver Nutter
On Tue, Feb 15, 2011 at 5:28 PM, Laurent Sansonetti
lsansone...@apple.com wrote:
 Hi Alan,
 Do you control the data structure that holds a reference to 'B'? If yes, you
 may want to use NSHashTable which supports weak references.
 To me, this sounds like a design problem. Maybe your project can be
 re-architectured to avoid this pattern.

Weak references and weak lists/hashes are often very useful for caches
you need to age out or when you need to associate data with a given
instance of an object without holding hard references. Using weak
references is definitely not a design problem in itself.

I'm also disappointed that you'd recommend people use NSHashTable
rather than just fixing WeakRef :) In JRuby, we nuked weakref.rb some
time ago because it has a lot of problems. Instead, we wrap the JVM's
builtin weakrefs.

See also the weakling gem, which (for JRuby) provides additional
features mentioned in that Ruby redmine ticket like reference queues
and a simple weak ID hash to use in place of _id2ref.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Ruby sort algorithm

2011-01-31 Thread Charles Oliver Nutter
On Sun, Jan 30, 2011 at 6:19 PM, Morgan Schweers cyber...@gmail.com wrote:
 Greetings,
 Ruby's sort algorithm is quicksort, last I checked, and quicksort is not
 stable (which is the property you're looking for in a sort).  There are a
 bunch of ways around this, including writing your own, but one cute, quick,
 but possibly performance-impairing, approach I've seen (Matz's suggestion)
 is:

FWIW, JRuby originally had a stable Array#sort, but because it was
slower than MRI's unstable sort (and we got bug reports to that
effect) we replaced it with an unstable hybrid sort based on
quicksort. Shortly after we did that, someone raised an issue against
MRI to get it to move to a stable sort :)

As far as I know, MRI hasn't changed yet.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Concurrency bug in ControlTower

2011-01-29 Thread Charles Oliver Nutter
On Wed, Jan 26, 2011 at 4:50 PM, Laurent Sansonetti
lsansone...@apple.com wrote:
 No, only locals and dynamic (block) variables.
 To be honest I always disliked this semantic change too. I think it was a
 mistake to add it. It will probably be reverted for 1.0.

I started to try to implement it, and it's not easy. I would need to
cascade all the way up the containing scopes, cloning each one. It's
very messy.

I would have no objections to this behavior going away.

What if instead of e.g. async, you had the following form:

queue.async(a, b) {|a, b| ... }

Because 1.9 forces variables in the block's argument list to be local
to the block, this would avoid the sharing of variables completely.

This would work with anything proc-like as well:

job = -(a, b) { ... } # block-local a and b
queue.async(a, b, job) # outer scope's a and b

Of course you might want to rename them in the block, to avoid
confusion, but this neatly does what tap did in my suggested fix
(and I don't know why I didn't think of it sooner).

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-28 Thread Charles Oliver Nutter
On Wed, Jan 26, 2011 at 4:45 PM, Laurent Sansonetti
lsansone...@apple.com wrote:
 Hi Charles!
 Sorry for the late response.
 As others have noted, in this snippet, #apply is called on a sequential
 queue (queues created by Queue.new are always sequential), therefore there
 shouldn't be any problem here. If the queue was concurrent, however, there
 would be a thread safety issue.
 I think this rdoc snippet should be rewritten to avoid confusion.

Yup, I understand now. Thank you!

 I see that you're wrapping a GCD-like interface in JRuby, it's very cool! I
 assume you want your interface to be cross platform, but in the case of
 JRuby running on Mac OS X, maybe we can extract our code as a C extension,
 this way JRuby would use the system GCD. Maybe we can also work together
 on creating a good test/spec suite for the GCD interface, because it's
 currently lacking.

To be honest I'm more and more downbeat about C extensions. On JRuby,
we have opted to disallow C extensions from running concurrently,
since there's just too many extensions that mutate global state. They
also make it impossible to spin up multiple JRuby instances in the
same JVM, since ALL C extensions hold references to a specific JRuby
runtime or classes it contains in global state (i.e. no extensions out
there are MVM-safe).

So there are certainly other possiblities:

1. FFI. The libdispatch APIs are all C-based and seem to be pretty
consistent. A single FFI binding might work for everyone including
MRI.
2. Attempt to build off Java/Cocoa integration, as seen in this
attempt: http://pixel.recoil.org/code/rococoa/index.html. I don't know
how reliable that integration is though, or if Apple is going to
continue maintaining it.

A C extension would probably be a last resort since it has many limitations.

re: testing: Yes! Are there many tests for this yet? I have not looked
for them, so I have no idea. I'd love to see a complete suite (or at
least complete for the highest-level surface area of functionality)
that we could all try to meet.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Concurrency bug in ControlTower

2011-01-26 Thread Charles Oliver Nutter
On Mon, Jan 24, 2011 at 11:13 AM, Joshua Ballanco jball...@gmail.com wrote:
 Regarding the potential bug...well...where to begin? So, yes, MacRuby blocks
 have the same semantics as regular Ruby blocks, *except* when they are
 dispatched through GCD. In that case, ivars are shared, but local variable
 get copied. I'm sure Laurent can explain why better than I, but it has to do
 with the semantics of libdispatch and the uncertainty inherent in when a
 dispatched block or function will execute (i.e. if local variables were not
 copied during dispatch, they might go out of scope and be collected before
 GCD ever gets around to running the code).

Wow, that's very surprising. I'm not sure I agree with bending Ruby
semantics so drastically, even to help concurrency. Or at least, I'd
expect other threaded scenarios to be consistent:

~ ➔ ruby -ve a = 0; Thread.new { a += 1 }.join; p a
MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64]
1

~ ➔ ruby -ve a = 0; q = Dispatch::Queue.concurrent; q.sync {a += 1}; p a
MacRuby 0.8 (ruby 1.9.2) [universal-darwin10.0, x86_64]
0

The implicitness in being able to mutate the surrounding scope is
certainly problematic. This is one reason Java's anonymous inner
classes require that referenced variables be declared final...to
indicate they can't be mutated by the body of the anonymous inner
class's methods.

The result is that people end up using one-element arrays and the
like, but people find ways around anything.

So I suppose this applies to anything in the surrounding scope,
including visibility, $~, and so on?

 To illustrate how this impacts async semantics wrt ruby, here's a sample
 done with MacRuby/GCD and canonical Ruby:

I'll see how this might be implemented in JRuby.

 In other words, not a bug in MacRuby...also, this code is scheduled for a
 rewrite that will turn it into a bit more of a continuation-passing style of
 handling the connections. I don't think tap is really the solution we are
 looking for here, since after dispatching, the main #accept loop doesn't
 really care about that connection (other than that, at some point, it is
 responsibly closed).

tap would be a clean way to explicitly isolate each loop's
environment, if you weren't already doing that.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-25 Thread Charles Oliver Nutter
On Tue, Jan 25, 2011 at 1:00 AM, Joshua Ballanco jball...@gmail.com wrote:
 On Mon, Jan 24, 2011 at 8:20 PM, Charles Oliver Nutter head...@headius.com
 wrote:
 I'm curious what you mean by this. Can you point out the code? Is it
 actually attempting to rewrite local variable or instance variable or
 array modifications in code?

 Sorry, I mis-remembered. Not a mix-in, but Dispatch::Proxy from the dispatch
 gem is what I was thinking of. It uses the delegator pattern to funnel all
 access through a serial queue. Admittedly, this technique is a bit heavy
 handed (and, I'm just now realizing, somewhat inefficiently implemented...).
 Still, it gets the job done...

Ok, got it. Unsurprisingly HawtDispatch also provides a built-in
queue-backed delegation proxy using Java reflection. Of course, we can
do a lot better than that in Ruby.

 I'm building a JRuby-based mimic API of the MacRuby GCD API:
 https://github.com/headius/jcd

 That sounds like an excellent idea! One issue that we've come across
 repeatedly in MacRuby is how to teach Ruby programmers to write grown-up
 thread-safe code (and, from my half-hearted attempts to follow what's going
 on in JRuby, it seems you've been dealing with this as well). That is,
 something like @my_array[i] += 1 is safe enough when you have a GIL, but
 is not when you have true low-level reentrancy. (In fact, even @my_array[i]
 = foo is not thread-safe!)

Yes, I think JRuby has helped force the issue for years, and now
MacRuby gets to help :)

Things used to be a lot worse. I remember spending long hours writing
emails and IM responses to people that were almost angry that I
decided JRuby's Array, Hash, and String would not be thread-safe. They
really didn't get why we couldn't just do what MRI does. It took a
lot of effort and a few favors from key greybeards in the Ruby
community for people to accept that JRuby was making the pragmatic
decision. And hopefully MacRuby has had an easier time selling such
decisions as a result.

The Ruby community has come a long way, but there's obviously more work to do.

 Instead of attempting to bring the world of spin-locks and mutexes (and when
 to use one instead of the other) into Ruby, I think it's probably more
 useful to introduce a transactional programming model. This LtU post comes
 to mind: http://lambda-the-ultimate.org/node/4070

Yes, you're right for most scenarios. There are of course many places
where queues or transactions are far too heavy. What we need to do is
ensure that as better concurrency models become available for
Rubyists, we do what we can to ensure they work across Ruby
implementations and share the load of educating users. That's what I
hope to do with JCD, and I hope someone will be able to do the same
for MRI in a way that works on all its supported platforms.

I have other concurrency-related projects you may be interested in:

The ruby-atomic gem, providing explicitly atomic references (and
CAS-like operations) on JRuby and MRI:
https://github.com/headius/ruby-atomic. I collaborated with MenTaLguY
on this one.

The cloby gem, which wraps Clojure's STM and Ref to allow creating
(J)Ruby objects with all transactional instance variables:
https://github.com/headius/cloby

I have also worked with MRI and Rubinius folks on various forms of
Multi-VM (MVM) API, providing a standard interface for launching
isolated ruby environments in the same process. Of course JRuby has
been able to do this for years (since org.jruby.Ruby is just another
object), but MVM and similar APIs may be the only way MRI ever gets
access to true in-process concurrency.

 Anyway, I'd be glad to lend a hand (and whatever slice of my limited time I
 can spare) to the effort. In particular, test suites/specs are difficult in
 this space, as the MacRuby team has learned first-hand.

I don't have a lot to offer in this area. We benefited years ago from
the big threadsafety push in Rails 2.2, by providing rails core a
32-way box and letting them beat the hell out of Rails and JRuby under
heavy concurrent load. I know of no similar efforts since, for any
library.

 What I have now is a mostly-complete Queue and Object, but I'm still
 figuring out how to map the other libdispatch primitives to what
 HawtDispatch provides. The library currently is complete enough to run
 a fork of ControlTower I made called ChaosBazaar:
 http://github.com/headius/ChaosBazaar

 So, now I'm curious: have you gotten to the dispatch_source_t part of
 libdispatch? I wonder, because this is where I would predict the most
 difficulty. In OS X, the dispatch sources are made possible through the use
 of a kqueue, which is kinda like a select but at the kernel level. Also,
 there might be some difficulty in mapping the semantics directly due to the
 high degree of asynchrony achieved by libdispatch. For example: the
 following is perfectly legal:
 myq = Dispatch::Queue.new
 myq.async do
   myq.cancel!
   *keep doing stuff on 'myq'*
 end
 ...because cancelation

Re: [MacRuby-devel] Thread safety in apply example?

2011-01-25 Thread Charles Oliver Nutter
On Tue, Jan 25, 2011 at 2:11 AM, Charles Oliver Nutter
head...@headius.com wrote:
 I did have to hack around the parser logic, since native extensions
 largely mean death for concurrency on JRuby (and by native I mean C
 extensions using MRI's API). Instead, I lifted code from Mongrel and
 Rack to use Mongrel's parser to populate a Rack environment, and
 managed to make the result function well enough to benchmark.

I should clarify this... Mongrel has shipped a Java version of its
Ragel-based parser for many years. JCD and ChaosBazaar have no
native/C code whatsoever, and will run on any platform with a
reasonably current JVM.

I'd be happy to roll my CT/CB parser hackage back into mainline if we
can find a clean way to isolate impl-specific backends. It would be
easier to maintain a single CT atop multiple GCD lookalike APIs than
to collaborate on largely-independent forks.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-24 Thread Charles Oliver Nutter
On Mon, Jan 24, 2011 at 10:24 AM, Matt Massicotte massico...@apple.com wrote:
 My guess is that most problems need a thread-safe mechanism, where 
 manipulating an array is just one part of a more complex system.  Pushing the 
 details of the thread-safety into the array just hides the problem, and will 
 likely trade more locking for possibly simpler code.

 Which could be a very good trade, don't get me wrong.  I'm not trying to 
 knock your implementation at all.

In some cases, it's a great trade. It's just not a trade-off you want
to make for *all* access, which is why concurrent-threaded Ruby impls
like JRuby and MacRuby don't make that guarantee for Array, Hash, etc.
Of course, regular C Ruby isn't concurrent-threaded, so they have had
little motivation to do *anything* to improve the state of concurrent
programming on Ruby, like adding thread-safe collections or simpler
synchronization mechanisms.

 I think the actual underlying problem here is Queue#apply's rdoc entry.  
 Manipulating a non-thread-safe data structure (which is all of Foundation's 
 collection classes) in an apply is a bug and even worse a conceptual error.  
 Where do you open bugs on the dispatch gem?

Queue#apply is actually defined in gcd.c in MacRuby's code, so this
would be a MacRuby bug. I'd have filed it, but I wasn't sure if I was
missing something about MacRuby's Array and thread-safety.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-24 Thread Charles Oliver Nutter
On Mon, Jan 24, 2011 at 11:26 AM, Joshua Ballanco jball...@gmail.com wrote:
 On Mon, Jan 24, 2011 at 12:15 PM, Charles Oliver Nutter
 head...@headius.com wrote:

 Queue#apply is actually defined in gcd.c in MacRuby's code, so this
 would be a MacRuby bug. I'd have filed it, but I wasn't sure if I was
 missing something about MacRuby's Array and thread-safety.

 Yeah, probably a documentation bug...but only sorta. Parallel/Not-Parallel
 will depend on the queue. Apply just queues the block asynchronously the
 number of times indicated by the argument. How the block executes depends on
 the queue.

Ok, that makes sense. The documentation implied that apply always runs
the jobs in parallel, so I assumed that meant they could potentially
run concurrently. If instead they're serial, the example as written
should be safe.

It seems like a poor example in any case, however, since someone might
assume using a concurrent queue is safe as well.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-24 Thread Charles Oliver Nutter
On Mon, Jan 24, 2011 at 11:39 AM, Jordan K. Hubbard j...@apple.com wrote:
 FWIW, we've tried this same approach experimentally (use a per-object serial 
 queue behind the scenes to implement an async setter / sync getter model) 
 over in CoreFoundation land, and it seemed to work reasonably well for the 
 most part.  We ran into some compatibility issues with a few of the methods 
 which just didn't lend themselves to a thread-safe object model, enough that 
 we couldn't simply do this as a completely transparent solution, but it 
 mostly Just Worked and I think MacRuby (or, for that matter, JRuby) could do 
 something very similar and probably get away with it since Ruby 
 arrays/hashes/strings aren't quite so inclined to hand pointers to their 
 internal state around to clients of the API.   Laurent doesn't exactly agree 
 with me since he's still focused on performance, but I think it should 
 definitely be possible to declare a Ruby object as contended in some way 
 such that everything then goes through a serial queue implicitly to access it 
 - I'm not saying this sh
  ould be true for every object, just the ones for which you need thread 
 safety.

I'd be extremely surprised if the overhead frrom making an object
thread safe with a queue wasn't much higher than simply synchronizing
all access with normal low-level locking primitives. It might be
useful to transparently proxy all calls targeting a specific object
through a queue-based delegator (as I believe you or someone has
rigged up in the Dispatch gem), but I'd be very surprised if it were a
good generally-applicable thread-safety mechanism for mutable state.

Sometimes you just need to use locks.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-24 Thread Charles Oliver Nutter
On Mon, Jan 24, 2011 at 11:23 AM, Joshua Ballanco jball...@gmail.com wrote:
 Arrays in MacRuby are not inherently thread safe. However,
 Dispatch::Queue.new creates a serial queue. So, there is an error in that
 each invocation of the block will execute serially. If, instead, the example
 had used Dispatch::Queue.concurrent, then there would be a potential bug,
 but the easiest way to work around that is:
 gcdq = Dispatch::Queue.concurrent
 @result = []
 @result_q = Dispatch::Queue.new('@result_assignment_queue')
 gcdq.apply(5) { |i| res = i * i; @result_q.async { @result[i] = res } }
 p @result

Yes, forcing the updates to run serially rather than in parallel. The
poor-man's fork/join.

 There's also a mixin available in the Dispatch gem which abstracts away the
 need for a serial queue for assignments by monkey-patching assignments to
 all happen on a serial queue.

I'm curious what you mean by this. Can you point out the code? Is it
actually attempting to rewrite local variable or instance variable or
array modifications in code?

 For those wondering about the advantages to this technique, it's worth
 noting that GCD has a much lower overhead than more traditional methods of
 parallelism. That said, if the calculation for each iteration is small, this
 is not a useful technique. However, if the calculation for each iteration is
 long or (more likely) non-deterministic -- as in waiting for an external
 call or a remote connection -- then this can be a useful technique to
 continue doing useful work while letting iteration complete in the
 background.

I suppose it's time to explain why I'm looking into this stuff at all.

I'm building a JRuby-based mimic API of the MacRuby GCD API:
https://github.com/headius/jcd

I started out using java.util.concurrent Executors directly, and later
moved to using HawtDispatch, a libdispatch-like API. The latter has
done a reasonably good job of matching the necessary dispatch_*
functions in an OO API, and for the pieces that exist the wrapping job
has been trivial.

What I have now is a mostly-complete Queue and Object, but I'm still
figuring out how to map the other libdispatch primitives to what
HawtDispatch provides. The library currently is complete enough to run
a fork of ControlTower I made called ChaosBazaar:
http://github.com/headius/ChaosBazaar

There's no real reason I shouldn't be able to support most of the
MacRuby GCD APIs using just what's available on the JVM (i.e. no
native or OS dependencies), which would allow those APIs to be used on
any platform (and GCD client code that's not otherwise bound to
MacRuby to work on JRuby without modification). I think that would be
a good thing for concurrency in the Ruby world.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-23 Thread Charles Oliver Nutter
On Sat, Jan 22, 2011 at 2:00 PM,  macr...@djc.net wrote:
 Taking
 http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html
 as a sign, the answer appears to be:
 neither of these can be safe, the latter even more so since the result is
 unordered.

Yes, that's not too surprising I guess

 If one is paranoid, not even sizing the array beforehand (a very good idea)
 is safe, unless someone can definitively state that no one (inc. MacRuby)
 will
 be modifying/moving/otherwise manipulating this mutable object while you
 are

That's certainly not specified behavior, although I *think* it would
always be safe in JRuby and MRI (don't know about MacRuby).

 a bit of a disappointment, since a) we know resizing occurs far less
 frequently then access (in general) b) making this all thread safe can
 easily be done at the Framework level c) most of the time, the behavior is
 exactly what we see here w.r.t. sizing (e.g. it grows UP, never down, and
 not up and down ... until GC kicks in and removes it all)

In JRuby we ship a nonstandard extension JRuby::Synchronized you can
include into any class (or object) to force all methods to be
synchronized. The example in that case would look like:

@result = []
@result.extend JRuby::Synchronized

Or even better, create a SyncArray subclass that includes it.

I'd like for there to be a standard way to do this across Ruby impls
(in particular, I'd like a standard set of thread-safe collections in
Ruby proper), but perhaps the JRuby solution will provide a starting
point for everyone else.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Thread safety in apply example?

2011-01-22 Thread Charles Oliver Nutter
On Sat, Jan 22, 2011 at 8:52 AM, Ernest N. Prabhakar, Ph.D.
prabh...@apple.com wrote:
 My assumption was that doing a parallel assign:

 result[i] = i*i

 would be safe, since it always accessed a unique portion of memory, but doing 
 a serial append:

 result  i*i

 would not.  But that may have been a mistake on my part, since the size (at 
 least) needs to be updated. Anyone know better?

I believe you're correct about the size update being the problem.
Unless the result array has all the space it needs initially, the
example could easily trigger it to resize, and with concurrent threads
all writing at the same time it's very likely some results will get
lost.

It could be improved slightly if you initialize @result with a
guaranteed-sized backing store, like this:

@result = Array.new(5)

This would ensure the array already has a 5 element backing store
prepared, and so concurrent writes would be writing different memory
locations. But it still seems like a bad precedent, since the
implementation details of doing concurrent writes to Array are hidden.
It could be maintaining an immutable linked list structure instead of
an array, in which case every random-access update would need to
modify all nodes in one direction or the other, and you're back to
concurrent mutation.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


[MacRuby-devel] Thread safety in apply example?

2011-01-21 Thread Charles Oliver Nutter
I'm curious about this example in Queue#apply's rdoc:

 * gcdq = Dispatch::Queue.new('doc')
 * @result = []
 * gcdq.apply(5) {|i| @result[i] = i*i }
 * p @result  #= [0, 1, 4, 9, 16, 25]

apply is said to issue the jobs in parallel, so this would be making
concurrent updates to the @result array. Are simple arrays in MacRuby
thread-safe?

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


[MacRuby-devel] Concurrency bug in ControlTower

2011-01-21 Thread Charles Oliver Nutter
Apologies reporting this here; I'm not sure where I should report bugs
in ControlTower.

I believe there's a bug in ControlTower around line 34:

def open
  @status = :open
  while (@status == :open)
connection = @socket.accept #  here

@request_queue.async(@request_group) do

The connection local variable is used in the async block below to
parse the request and send the response. Unless MacRuby's blocks
behave differently than regular Ruby, this variable is shared across
all activations of that block. As a result, it's possible that two
concurrent requests will end up using each others' connection, and
usually just blowing up as a result.

The fix I've come up with is to wrap the @request_queue.async call in
a tap call:

def open
  @status = :open
  while (@status == :open)
conn = @socket.accept

conn.tap do |connection|
  @request_queue.async(@request_group) do

Since async can't accept any explicitly-passed state, this seems like
the safest way to ensure the connection reference is not shared by
separate invocations. I'm not sure if it's possible in GCD, but having
async take an optional argument with explicitly-passed state might
also be a good way to fix this.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Static Typing

2011-01-18 Thread Charles Oliver Nutter
On Thu, Jan 6, 2011 at 1:26 AM, Henry Maddocks henry.maddo...@gmail.com wrote:
 Neither of those projects have anything to do with MacRuby and as far as I 
 can they don't have much to do with MRI either so their impact will be 
 academic at best. The Mirah project is trying to make ruby more like Java. 
 Well there already is a language a lot like Java, it's called Java. If you 
 prefer the Obj-C way of doing things then feel free to use Obj-C. Me, I like 
 [Mac]Ruby just the way it is.

Mirah is not trying to make Ruby more like Java. It uses Ruby syntax
and its apparent features as a starting point, and maps than as
directly to the JVM's type system and libraries as possible. It is a
Ruby syntax for writing JVM code. It is not Ruby. It does not intend
to be Ruby. It does not intend to change Ruby.

People are writing and running production applications with Mirah
already, so the impact is more than academic even now.

I am certainly interested in the potential of static or gradual typing
in Ruby, but it's as much a research topic as anything. My use case
would be to eliminate dynamic dispatches when explicit target can be
determined, and to improve performance of code that does heavy numeric
algorithms by making it possible to optimize them down directly to
primitive CPU maths.

I will repeat, though: Mirah is not a statically-typed Ruby. It is a
new language that borrows Ruby's (beautiful) syntax and maps it
directly to statically-typed JVM code.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Return from thread context

2009-07-11 Thread Charles Oliver Nutter
On Fri, Jul 10, 2009 at 3:02 PM, Laurent
Sansonettilsansone...@apple.com wrote:
 Now, consider:

 def foo
  begin
    yield
  ensure
    p :ok
  end
 end
 def bar
  foo { return 42 }
 end
 p bar

 Here you don't have a choice, since you need to honor the ensure block.

 In Ruby, return is semantically similar to an exception in some cases. This
 is unfortunate :-)

Return isn't really an exception, since you can't catch/rescue it. The
issue here is that ensure blocks are a hard requirement, and they must
fire even if a non-local return unrolls through them. The return here
doesn't necessarily need to be implemented as an exception, but it
does need to fire ensure blocks.

In JRuby, we do use an exception, but we don't have any other way of
unrolling the stack.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Contributions (Was: Experimental branch status)

2009-06-05 Thread Charles Oliver Nutter

Eloy Duran wrote:
What would be great is if you could first complete the openssl part of 
the rubyspec, which desperately needs some love.


Wow, I concur a thousand times over. I'd love to have a complete set of 
OpenSSL specs out there, but I'm totally underqualified to write them.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] A MacRuby-users group?

2009-05-24 Thread Charles Oliver Nutter

Laurent Sansonetti wrote:

Hi Łukasz,

This mailing-list was usually created for all people developing with 
MacRuby, not necessarily people developing MacRuby itself. But I can 
understand that the group name is ambiguous.


Just to let everyone know, there is absolutely no problem posting 
anything related to MacRuby on this list. It's also true that there are 
more users discussions than core discussions here, but this might change 
once we get more people involved in the project. I think that the list 
traffic is still very light so I wonder if we need 2 separate lists.


Any though? If most people agree to create a -users group I can ask for 
an official (macosforge.org) one.


Bleh...most projects I'm on have separate dev and user lists, and I hate 
it (including JRuby). Half the time people aren't sure which list to 
post to, and none of those projects (nor MacRuby) have enough traffic to 
really need separate lists.


I'd say keep it all on one list for as long as possible.

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Strings, Encodings and IO

2009-04-08 Thread Charles Oliver Nutter

Vincent Isambart wrote:

I think everyone agrees that having a Ruby 1.9 String specs will be
necessity. And we'll also need to decide what parts of it to follow
and what parts we do not need to. For example handling access to
characters in a string with a partly invalid encoding exactly the same
way as 1.9 seems hard to do:


GOD yes...any sort of complete string specs would be most welcome. 
Marcin Mielzynski, our porting machine, believes that oure 1.9 String 
stuff is basically done--and true to form the test_string tests in Ruby 
1.9 repository do seem to mostly function--but I have no confidence in 
the coverage and completeness of the existing tests (having spent almost 
no time actually looking at them, though).


We have also been kicking around how to transparently handlg UTF-16 by 
just using Java strings...but having moved to our own Oniguruma port, it 
would mean some regexp behaviors would have to change back to Java regex 
behavior. We simply could not match Ruby regex exactly until we ported 
the same engines Ruby uses :(


- Charlie

- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Strings, Encodings and IO

2009-04-08 Thread Charles Oliver Nutter

Vincent Isambart wrote:

the test_string tests in Ruby 1.9 repository do seem to mostly function

You mean test/ruby/test_m17n.rb, test/ruby/test_m17n_comb.rb,
test/ruby/test_io_m17n.rb and test/ruby/enc/test_*.rb?
test/ruby/test_string.rb does not contain anything m17n related.


We simply could not match Ruby regex exactly until we ported the same engines 
Ruby uses :(

No two regexp engines have the same behavior, there's nothing anyone
can do about that...


Well, the problems we ran into is that those behavioral differences 
hindered our ability to run stuff like Rails. We didn't really have a 
choice.



It looks like Oniguruma has a support for UTF-16 so I was thinking
about using that in MacRuby. But as Oniguruma sees everything as a
list of bytes, I do not know if you could use the Oniguruma UTF-16
support without modifying your Oniguruma port.


Yes, I have talked with Marcin about us doing a separate fork of JOni 
that works with Java's UTF-16 characters directly. I think it could 
become the best Java regexp engine.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Strings, Encodings and IO

2009-04-07 Thread Charles Oliver Nutter

Vincent Isambart wrote:

Hi again,

So plan B: We emulate Ruby 1.9 strings behavior on top of of NSString/NSData.


I'm really interested in this discussion too. A little background for JRuby:

We started out (or really, the original authors started out) with JRuby 
using all Java strings and stringbuffers for Ruby's String. This made 
interop easy and of course simplified implementation, but it ran into 
the same problems you enumerated in your original post:


* Java's strings are all UTF-16. In order to represent binary data, we 
ended up using a raw encoder/decoder and only using the bottom byte of 
each character. Wasteful, since every string was 2x as large, and slow, 
since IO had to up/downcast byte[] contents to char[] and back.
* So we made a move about two years ago to using all byte[]-based 
strings in JRuby. This allowed us maximum compatibility, maximum 
performance, and a future-proof path, but it damages interop. Currently 
whenever you pass a string across the Ruby/Java boundary, we have to do 
the decode/encode. That affects performance pretty severely. We also had 
to implement our own regular expression engine, since no Java regex 
works with byte[].
* We want to move to an intermediate version, where we sometimes have a 
byte[]-backed string and sometimes a char[]/String-backed string. 
IronRuby does this already. This is, however, predicated on the idea 
that byte[]-based strings rarely become char[]-based strings and vice 
versa. I don't have any evidence for or against that yet.


So it's a nearly identical problem for MacRuby, as I understand it. I'm 
interested in discussion around this topic, since we are still moving 
forward with JRuby and would like to improve interop with Java 
libraries. I will offer the following food for thought:


* Going with 100% objc strings at first is probably a good pragmatic 
start. You'll have the perf/memory impact of encoding/decoding and 
wasteful string contents, but you should be able to get it functioning 
well. And since interop is a primary goal for MacRuby (where it's been 
somewhat secondary in JRuby) this is probably a better place to start.
* We have considered having a modified 1.9 mode that normalizes all 
strings into UTF-16 internally. That might work for you as well. I 
presume there are byte-decoding APIs in objc that could produce your 
standard strings. You'd be able to at least pretend you support 1.9 
encoding, but be transcoding to the user's selected encoding. It 
wouldn't be fast, but it would work.
* Alternatively, you could only support a minimum set of encodings and 
make it explicit that internally everything would be UTF-16 or MacRoman. 
In MacRuby's case, I think most people would happily accept that, just 
as a lot of JRuby users would probably accept that everything's UTF-16 
since that's what they get from Java normally.


Ultimately this is the exact reason I argued over a year ago that Ruby 
1.9 should introduce a separate Bytes class used for IO. I was denied.


It's definitely a sticky issue, and Ruby has made it even stickier in 
1.9 with arbitrary encoding support. None of the proposed solutions 
across all implementations (including JRuby) have really seemed ideal to me.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] Running the experimental branch

2009-04-04 Thread Charles Oliver Nutter

Laurent Sansonetti wrote:
For instance, the optimizations that are (and will be) implemented in 
the experimental branch are not random but were selected after having 
profiled a big MacRuby/Cocoa application and found many areas where we 
performed badly. I assume that other implementations are using similar 
techniques.


The interesting thing about many of these microbenchmarks is that a 
substantial part of MacRuby's performance seems to come from one key 
optimization: recursive calls.


MacRuby (experimental) fib(30) with fcalls (fib(...):
  0.06   0.00   0.06 (  0.053868)
  0.05   0.00   0.05 (  0.053773)
  0.05   0.00   0.05 (  0.055541)
  0.05   0.00   0.05 (  0.049992)
  0.06   0.00   0.06 (  0.054645)

MacRuby (experimental) fib(30) with calls (self.fib(...)):
  0.18   0.00   0.18 (  0.182371)
  0.18   0.00   0.18 (  0.178691)
  0.17   0.00   0.17 (  0.177174)
  0.17   0.00   0.17 (  0.179554)
  0.18   0.00   0.18 (  0.181848)

The latter numbers are roughly the same as JRuby performance without 
recursion optimization (with or without fcall).


The recursion opt is actually pretty clever...I experimented with it a 
few weeks back (achieving similar results, http://gist.github.com/67329) 
and backed off temporarily to work on other things. I also wasn't sure 
how common it would be in real code, nor was I sure it could be done 
safely while maintaining all Ruby semantics. Maybe we'll be able to 
figure that out together. :)


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] branches/experimental

2009-03-30 Thread Charles Oliver Nutter

Matt Aimonetti wrote:

Hi Charlie,

 I don't think/hope you do it on purpose, but it seems that you're 
asking questions just to prove that Laurent is wrong and that whatever 
he will do will end up slowing down the current experimental branch.


I think you're misinterpreting me. I'd love for Laurent to be right, and 
I'd love to know how to get around the cases that end up slowing down 
JRuby. I sincerely hope it's possible, since it would mean JRuby can 
probably do whatever MacRuby does in those cases. And I may be able to 
help if some of the optimization ideas are discussed more openly; I had 
similar discussions with IronRuby folks at RubyConf 2007 and saved them 
going down a path that I knew would eventually break code.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] branches/experimental

2009-03-30 Thread Charles Oliver Nutter

Charles Oliver Nutter wrote:

Matt Aimonetti wrote:

Hi Charlie,

 I don't think/hope you do it on purpose, but it seems that you're 
asking questions just to prove that Laurent is wrong and that whatever 
he will do will end up slowing down the current experimental branch.


I think you're misinterpreting me. I'd love for Laurent to be right, and 
I'd love to know how to get around the cases that end up slowing down 
JRuby. I sincerely hope it's possible, since it would mean JRuby can 
probably do whatever MacRuby does in those cases. And I may be able to 
help if some of the optimization ideas are discussed more openly; I had 
similar discussions with IronRuby folks at RubyConf 2007 and saved them 
going down a path that I knew would eventually break code.


Hmm, I just realized more openly sounded bad. I just mean I'm here if 
anyone wants to discuss ideas, and I might be able to help. Carry on! :)


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] branches/experimental

2009-03-29 Thread Charles Oliver Nutter

Laurent Sansonetti wrote:
I don't think it's a good idea to provide a way to turn off 
optimizations and I do not see the point in benchmarking dead code in 
general (I would never do this).


I think it's actually very useful to provide a way to turn off specific 
optimizations, if only because they may eventually run into cases where 
they break something. But they're also useful when writing benchmarks 
that have dead code on purpose...


For some benchmarks it's very difficult to get a reasonable measurement 
without forcing some dead code to run. For example, benchmarking a 
single local variable access gets completely lost in the method or block 
invocation that surrounds it. By forcing several successive local 
variable accesses to execute, you get a better picture of what the 
actual cost is.


At any rate, if you have good benchmarks for things like local 
variables, we can certainly use those for now.


Good to know, I just hope they are not doing this 30 million times in a 
loop or something :-)


Well, it gets called numerous times per request.

In the end, though, Rails performance has not actually been very 
execution-bound. We've had Ruby code running faster than Ruby 1.8 for 
almost two years, but we only recently started to post 10-20% 
performance gains for Rails itself. Rails performance, and probably most 
large applications' performance, all seem heavily dependent on core 
classes being as blazing fast as possible. It's a balancing act, and we 
often completely ignore execution performance for a whole release to 
work on core classes instead.


Yes, Binding is not implemented yet. Do not worry I have read the MRI 
source code and know how Binding works and how to provide a compliant 
implementation. Please stay tuned.


Well, I'd certainly like to hear what you're planning for this 
particular case. Just let me know when you're ready to talk about it. 
I've gone over several options when optimizing JRuby, and the 
block-as-binding issue makes most of them infeasible.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


Re: [MacRuby-devel] branches/experimental

2009-03-28 Thread Charles Oliver Nutter

Laurent Sansonetti wrote:
It's possible by modifying the source code and comment the call to 
createInstructionCombiningPass() and createCFGSimplificationPass(), but 
I do not recommend to remove these because I think it would break the 
way we compile Dwarf exception handlers in blocks.


# In my personal benchmark suite I try to make sure these optimizations 
do not provide false positive numbers when comparing against YARV.


Ok, it would be nice if there were a simpler way to turn those off; I 
don't want to break 'experimental' completely, but it would be nice to 
get real benchmark results in these cases.


Yes, currently calling eval with a literal string will call the JIT, so 
doing this in a loop will most likely eat all your memory :-)


I plan to address that later by fallbacking to the LLVM interpreter in 
some cases, but I doubt this will affect real-world applications. Also, 
there are ways to improve the JIT (nothing has been done yet).


In Rails, as recently as 2.2 (I haven't checked 2.3) there's a small bit 
of eval'ed code used to look up constants. Before we fixed our parser 
performance, we found it was a bottleneck. So that's at least one 
real-world case.


Yes as you noticed Binding has not been implemented yet :-( This is on 
the very top of my TODO list (needed for IRB) and I already know how to 
implement it without disabling our current local variables into CPU 
registers optimization.


How will you do that? Given that a block can be used as a binding, you 
can't statically inspect contained blocks to determine which variables 
are used and which aren't. For example, this code:


  def foo
a = 1
bar { }
puts a
  end

  def bar(b)
eval a = 2, b.binding
  end

  foo

This should print out 2 but prints out 1 in 'experimental' right 
now. This one feature is the primary reason JRuby can only put local 
variables in registers when there's no blocks present. When there's a 
block present, any variable can be accessed via its binding at any time. 
I've argued for this feature to be removed, but I have been unsuccessful.


Current JRuby is also putting local variables in registers (via HotSpot 
doing so for Java locals) when there's no blocks present.


- Charlie
___
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel