Juan Manuel Cuello | 2 Feb 01:34
Picon

Re: to_json performance


"Valium helps a bit here (it should be in AR core in my opinion), it
can selectively pick the columns you need and it will return back
values in an Array per every object, so we can have something like
this: `[['a', 'b', 'c'], ['a', 'c', 'd']]` "

ActiveRecord now has 'pluck' which I think does the same.



On Fri, Jan 27, 2012 at 3:26 AM, Claudio Poli <masterkain <at> gmail.com> wrote:
Originally posted on github, reported to the right place.

I would like to open a discussion about how `to_json` and `as_json`
operates in Rails from a performance standpoint.

I'm using Rails 3.2 but this issue applies to almost all versions of
Rails.

Our use case presents the challenge in sending out potentially large
JSON (or XML, but we'll focus on JSON rendering here) bodies as a
response of a API calls that runs through a normal Rails controller.

Someone states that if you are sending out more than 1MB of data
"you're doing it wrong".
I respectfully disagree, as there are different cases, based also on
what an application should do and is designed for.

There can be few major bottlenecks in rendering JSON as fast as
possibile from start to finish, three of them are:

* database query
* AR objects instantiation
* collection transformation in JSON

I'll exclude the AR timings, so let's tackle the first problem, AR
objects.

Having a result set of 50k entries is obviously painful, and doing it
with AR it will kill your instance, no questions asked.
Worse, in my use case this result set can be asked frequently from the
client.
This however can be easily solved by using a sapient mixture of
`caches_action`and `stale?`, although there may be few key issues when
using memcached and friends, because especially in managed
implementations, they may not support data keys larger than 1MB.

Since instantiating AR objects it's out of the question let's focus
and getting what we really want for our tests, an 'attribute' Hash to
convert to JSON.
Valium helps a bit here (it should be in AR core in my opinion), it
can selectively pick the columns you need and it will return back
values in an Array per every object, so we can have something like
this: `[['a', 'b', 'c'], ['a', 'c', 'd']]`

With little sorcery we can transform each Array representing the
requested record values in a Hash with keys mapped, like so:

   class Hash
     def self.transpose(keys, values)
       self[*keys.zip(values).flatten]
     end
   end

   keys = %W{token artist album genre release_year title duration
duration_in_seconds position play_count favorited disc_number}
   my_hash = <at> playlist.media_files.ordered.values_of(*keys).collect{ |
v| Hash.transpose(keys, v) }

Nice, now we have a Array of Hash without instantiating AR objects but
with all the info we need about our objects.
This operation proved to be _extremely_ fast even if we are
transforming and inserting 50k records.

Now, on to the rendering:

   render json: my_hash

This should try to call `to_json`on the Hash.

Since few Rails versions JSON encoding has been delegated to
`MultiJson`, which is ok.
Needless to say I'm using and requiring `yajl-ruby`, so I'm pretty
confident that MultiJson will pick it up as my engine, and in fact it
is:

   1.9.3p0 :001 > MultiJson.engine
    => MultiJson::Engines::Yajl

The key issue here is that with a large Hash the render action takes
36786ms to finish ( of which 8253.6ms spent for the database query,
that high because of multiple ORDER BY, that's another matter).

So I tried another way:

   render text: Yajl::Encoder.encode(my_hash)

Using `Yajl::Encoder.encode`(or `MultiJson.encode`for that matter)
yields another kind of result: 12614ms (8253.6ms always spent on the
database query)

Is there something we can do about this?

Note:
some may point out to try few gems like `rabl`or `acts_as_api`, but
don't forget they are mainly for presentation purpose and they are
comparable to the `to_json` performance in this regard.

Thanks for reading.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Matt Jones | 5 Feb 00:12
Picon
Gravatar

Interoperating ActiveResource and ActionController::Responder

I've just created a pull request to finally make ActiveResource correctly handle validation errors
returned from ActionController::Responder's default JSON handling code. The code also handles the
format produced by pre-3.2 Responders *and* the format previously expected by ActiveResource, so it
shouldn't break in any application that was working before.

https://github.com/rails/rails/pull/4881

Would appreciate any feedback - it would be nice for the framework to actually work with its own API endpoints...

Thanks,

--Matt Jones

--

-- 
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.

eduludi | 1 Feb 13:37
Picon

ActiveResource Associations

Hi! I want to know why this pull request (https://github.com/rails/
rails/pull/70) was not merged to master yet. This feature is very
usefull! Any idea? Thanks!

--

-- 
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.

Juan Manuel Cuello | 7 Feb 16:06
Picon

Re: Buffered logs in Rails 3.2.1

I think it is related to this:




On Sat, Jan 28, 2012 at 7:36 AM, thoughtafter <thoughtafter <at> gmail.com> wrote:
I just upgraded my first application to Rails 3.2.1.  It's been pretty
smooth which I appreciate.  However I have noticed that my production
log is now buffered.  It use to flush on every response but now it
does not.  I would like to restore the previous behavior bug I have
not found any information on how to do so.  If anyone knows how to do
this I would appreciate hearing it.

Thank you.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Jason King | 7 Feb 20:14
Picon

Re: ActiveResource Associations

Looks like there was an original question/request from José about supporting the standard nested resource URLs, and the author never updated it and a stalemate ensued.

On Wed, Feb 1, 2012 at 4:37 AM, eduludi <eduludi <at> gmail.com> wrote:
Hi! I want to know why this pull request (https://github.com/rails/
rails/pull/70
) was not merged to master yet. This feature is very
usefull! Any idea? Thanks!

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Gaston Ramos | 7 Feb 20:38
Picon
Gravatar

Re: ActiveResource Associations

El Tue, 07 de Feb de 2012, a las 11:14:43AM -0800, Jason King dijo:
> Looks like there was an original question/request from José about
> supporting the standard nested resource URLs, and the author never updated
> it and a stalemate ensued.

I have never updated it because I was waiting a pull request aproval. It never
happened. If some guy from rails-core tells me that it will be merged, I'll do
it.

regards.

-- 
"I always thought Smalltalk would beat Java, I just didn't know it would be
called 'Ruby' when it did."

   (Kent Beck)

+-------------------------------------+
Gastón Ramos
http://gastonramos.com.ar/
GNU/Linux Counter user #450312

--

-- 
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.

Jason King | 7 Feb 22:46
Picon

Re: ActiveResource Associations

Oh, you're the author?

Ok, so this is the stalemate I spoke of.  Core team is waiting for you get behind your patch and update it before merging or even showing interest.  You're waiting for the core team to merge or show interest before updating.

In my experience, core team are very busy, and new features often come second to bug fixes, and the onus usually resides with the author to make it as easy as possible for them to integrate the new feature without anything unexpected coming into Rails.  I'd say that right now what you have would create an unexpected result, for those nested URLs.  So the ball is really in your court :)

On Tue, Feb 7, 2012 at 11:38 AM, Gaston Ramos <ramos.gaston <at> gmail.com> wrote:
El Tue, 07 de Feb de 2012, a las 11:14:43AM -0800, Jason King dijo:
> Looks like there was an original question/request from José about
> supporting the standard nested resource URLs, and the author never updated
> it and a stalemate ensued.

I have never updated it because I was waiting a pull request aproval. It never
happened. If some guy from rails-core tells me that it will be merged, I'll do
it.

regards.

--
"I always thought Smalltalk would beat Java, I just didn't know it would be
called 'Ruby' when it did."

  (Kent Beck)


+-------------------------------------+
Gastón Ramos
http://gastonramos.com.ar/
GNU/Linux Counter user #450312

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Sam Grönblom | 9 Feb 04:29
Picon

memoize and invalidation - backwards?

Maybe this is because I'm missing something but it seems to me that
asking users of a memoized method to know when the method needs to be
reloaded is a bit backwards. To me it seems like whoever is messing
with something that affects the results of the memoized function
should be the one that after doing its work should call something like
memoized_method(:reset). Thoughts?

--

-- 
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.

Xavier Noria | 11 Feb 13:10
Gravatar

5x speedup in inflections

Hi gents,


I am playing around with an idea to improve the performance of singularize and pluralize for Rails 4.0. In my proof of concept I see some 5x boost, but it relies an assumption that I'd like to consult with you all. Let me explain.

As you know, inflection rules have a lhs which is a string or regexp, and a replacement string as rhs.

The current implementation collects the rules in an array, and to apply them to a particular word the array is iterated. The first pattern that matches is the one applied. In particular, the most common rule (eg append "s" to form a plural), is the *last* one because most specific rules come first. By default we have +30 rules for singulars and +30 for plurals.

My idea is to build a single regexp with an alternation, detect which segment matches, and apply its replacement. That is, let the regexp engine itself do the loop. Much faster.

I have this working with a quick hack that has shown there's a potential speedup here. To be able to know which regexp is the one that matched I use named captures. For example (?<_25>(ax)is) would be the alternation corresponding to the regexp /(ax)is/, if that's the 26th pattern. It won't win me an elegance award, but it is a hack that works (I could workaround name clashes easily if the user happens to use _25 himself, that's not important).

Named captures are the only way I've seen to be able to build the alternation and at the same time know which part matches. Because existing inflection regexps have captures.

This is the proof-of-concept: https://gist.github.com/1798985.

I believe this is correct *as long as* the user regexps have no backreferences, because if you have a = /(..)\1/ and b = /(.)\1/ then "xx" matches b, but does not match the union a|b because the backreference \1 in b now refers to the group in a.

OK, so this is the question: do you guys use backreferences in custom inflections? If you didn't we could consider ruling them out for 4.0 to be able to implement this.


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group.
To post to this group, send email to rubyonrails-core <at> googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-core+unsubscribe <at> googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Aaron Patterson | 12 Feb 02:10
Favicon

Re: 5x speedup in inflections

On Sat, Feb 11, 2012 at 01:10:27PM +0100, Xavier Noria wrote:
> Hi gents,
> 
> I am playing around with an idea to improve the performance of singularize
> and pluralize for Rails 4.0. In my proof of concept I see some 5x boost,
> but it relies an assumption that I'd like to consult with you all. Let me
> explain.
> 
> As you know, inflection rules have a lhs which is a string or regexp, and a
> replacement string as rhs.
> 
> The current implementation collects the rules in an array, and to apply
> them to a particular word the array is iterated. The first pattern that
> matches is the one applied. In particular, the most common rule (eg append
> "s" to form a plural), is the *last* one because most specific rules come
> first. By default we have +30 rules for singulars and +30 for plurals.
> 
> My idea is to build a single regexp with an alternation, detect which
> segment matches, and apply its replacement. That is, let the regexp engine
> itself do the loop. Much faster.
> 
> I have this working with a quick hack that has shown there's a potential
> speedup here. To be able to know which regexp is the one that matched I use
> named captures. For example (?<_25>(ax)is) would be the alternation
> corresponding to the regexp /(ax)is/, if that's the 26th pattern. It won't
> win me an elegance award, but it is a hack that works (I could workaround
> name clashes easily if the user happens to use _25 himself, that's not
> important).
> 
> Named captures are the only way I've seen to be able to build the
> alternation and at the same time know which part matches. Because existing
> inflection regexps have captures.

It's possible to count the number of captures in a given regexp:

    def count_captures regexp
      Regexp.union([regexp, //]).match('').captures.length
    end

    p count_captures /(ax)is/     # => 1
    p count_captures /((ax)is)/   # => 2
    p count_captures /(?:(ax)is)/ # => 1

With that information, you can calculate offsets.  Calculating offsets
would still result in a linear scan (since you'd have to keep a list of
the offsets, then find the one that matched), and since we can use named
captures on 1.9, I'm not sure an offset based solution would be great.

> This is the proof-of-concept: https://gist.github.com/1798985.

Seems good, but you don't need a *args to Regexp.union. :-)

> I believe this is correct *as long as* the user regexps have no
> backreferences, because if you have a = /(..)\1/ and b = /(.)\1/ then "xx"
> matches b, but does not match the union a|b because the backreference \1 in
> b now refers to the group in a.
> 
> OK, so this is the question: do you guys use backreferences in custom
> inflections? If you didn't we could consider ruling them out for 4.0 to be
> able to implement this.

If you can rule out backreferences, it seems possible you could build a
state machine that would perform in linear time to the string length.
It seems though, with your algorithm, as the string gets longer, the
original implementation is faster:

  https://gist.github.com/1805359

Do we know what kind of data we're dealing with?  Somewhere between
strings of length 10 and strings of length 100, the original code
outperforms this version.  If we're only dealing with shorter strings,
maybe this newer code would be better.

One last comment, the line:

  name = md.names.detect {|n| md[n]}

The length of `names` increases as the number of rules is added to the
system.  Which means in the case of a match, this algorithm will still
be O(n), where n is the number of rules defined.  We can see this by
testing strings that match first and strings that match last:

  https://gist.github.com/1805536

I'm using AS 3.2.1, so "zombies" will be best case, and a bunch of x's
will be worst.

If we're willing to limit the type of expressions provided to the
inflector, it's possible to construct something that matches the string
regardless of the number of rules (entries in "inflections.rb"), and
proportional to the string length.

MEOW MEOW MEOW MEOW

<3 <3 <3 <3 <3 <3

--

-- 
Aaron Patterson
http://tenderlovemaking.com/

Gmane