Last Comment Bug 673473 - Remove off-main-thread JSRuntime use in GetKeyPathValueFromStructuredData
: Remove off-main-thread JSRuntime use in GetKeyPathValueFromStructuredData
Product: Core
Classification: Components
Component: DOM (show other bugs)
: unspecified
: All All
-- normal (vote)
: mozilla8
Assigned To: Luke Wagner [:luke]
: Andrew Overholt [:overholt]
Depends on:
Blocks: 650411
  Show dependency treegraph
Reported: 2011-07-22 10:56 PDT by Luke Wagner [:luke]
Modified: 2011-08-02 03:24 PDT (History)
5 users (show)
See Also:
Crash Signature:
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---

patch (8.02 KB, patch)
2011-07-25 15:57 PDT, Luke Wagner [:luke]
bent.mozilla: review+
Details | Diff | Splinter Review
patch (1.53 KB, patch)
2011-07-27 14:22 PDT, Luke Wagner [:luke]
no flags Details | Diff | Splinter Review

Description User image Luke Wagner [:luke] 2011-07-22 10:56:26 PDT
Spun off from bug 668915.
Comment 1 User image Luke Wagner [:luke] 2011-07-22 10:58:34 PDT
IIUC, the simplest immediate solution is to associate a new runtime with the IDB thread and use this in GetKeyPathValueFromStructuredData.  This code is, like, really pretty nice and readable (hg annotate says kudos to bent), so I'm going to take a crack at it unless someone else is itching to.
Comment 2 User image Luke Wagner [:luke] 2011-07-25 15:57:10 PDT
Created attachment 548316 [details] [diff] [review]

I was hoping to associate the JSRuntime/JSContext with some long-lived-but-single-threaded IndexedDB object, but I couldn't find one.  Lacking that, the simplest thing seems to be to just to use TLS and rely on the destroy hook to clean up.  With this patch, none of my single-threaded-runtime asserts hit for tests/dom/indexedDB.

One note about the patch: I added ThreadLocalJSRuntime (instead of just storing cx as the TLS value) so that we'd have a place to hold the global object when we get around to bug 604813.
Comment 3 User image Luke Wagner [:luke] 2011-07-27 14:22:43 PDT
Created attachment 548916 [details] [diff] [review]

On second thought, abort() may be a bit harsh.
Comment 4 User image Luke Wagner [:luke] 2011-07-27 14:23:21 PDT
Comment on attachment 548916 [details] [diff] [review]

Oops, wrong bug.
Comment 5 User image Ben Turner (not reading bugmail, use the needinfo flag!) 2011-07-28 12:27:17 PDT
Comment on attachment 548316 [details] [diff] [review]

Review of attachment 548316 [details] [diff] [review]:

Looks great, thanks for tackling this!

::: dom/indexedDB/IDBObjectStore.cpp
@@ +241,5 @@
>  class CreateIndexHelper : public AsyncConnectionHelper
>  {
>  public:
> +  CreateIndexHelper(IDBTransaction* aTransaction, IDBIndex* aIndex);

I think you can still keep this inlined, right?

@@ +264,5 @@
>  private:
>    nsresult InsertDataFromObjectStore(mozIStorageConnection* aConnection);
> +  static void DestroyTLSEntry(void* ptr);

Nit: params get 'aPtr' style names

@@ +2197,5 @@
>    return WrapNative(aCx, cursor, aVal);
>  }
> +static const PRUintn BAD_TLS_INDEX = (PRUint32)-1;
> +PRUintn CreateIndexHelper::sTLSIndex = BAD_TLS_INDEX;

Can you move these up right after the class definition?

@@ +2201,5 @@
> +PRUintn CreateIndexHelper::sTLSIndex = BAD_TLS_INDEX;
> +
> +class ThreadLocalJSRuntime
> +{
> +  JSRuntime *mRuntime;

Nit: * goes on the left here ;)

@@ +2210,5 @@
> +  static const unsigned sRuntimeHeapSize = 64 * 1024;  // should be enough for anyone
> +
> +  ThreadLocalJSRuntime() : mRuntime(NULL), mContext(NULL), mGlobal(NULL) {}
> +
> +  nsresult Init()

This can be private. Also, since the error code isn't really important you could just make this return boolean...

@@ +2259,5 @@
> +  }
> +};
> +
> +JSClass ThreadLocalJSRuntime::sGlobalClass = {
> +  "IndexedDBOffThreadGlobal",

Nit: s/Off/Transaction/

@@ +2269,5 @@
> +CreateIndexHelper::CreateIndexHelper(IDBTransaction* aTransaction,
> +                                     IDBIndex* aIndex)
> +  : AsyncConnectionHelper(aTransaction, nsnull), mIndex(aIndex)
> +{
> +  if (sTLSIndex == BAD_TLS_INDEX)

Nit: Please brace single line if statements.

@@ +2409,5 @@
>      PRUint32 dataLength;
>      rv = stmt->GetSharedBlob(1, &dataLength, &data);

Error codes returned from this function have to be NS_ERROR_DOM_INDEXEDDB_* errors. Probably want NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR here.

Nit: newline after this

@@ +2415,5 @@
> +      reinterpret_cast<ThreadLocalJSRuntime*>(PR_GetThreadPrivate(sTLSIndex));
> +
> +    if (!tlsEntry) {
> +      tlsEntry = ThreadLocalJSRuntime::Create();

Same here, and a newline too!
Comment 6 User image Luke Wagner [:luke] 2011-07-28 14:17:45 PDT
(In reply to comment #5)
> > +  CreateIndexHelper(IDBTransaction* aTransaction, IDBIndex* aIndex);
> I think you can still keep this inlined, right?

I could but I thought it would be more readable if the TLS logic in the body was next to all the other TLS logic.  Does this sway you?

> > +  nsresult Init()
> This can be private.

It is :)

> Also, since the error code isn't really important you
> could just make this return boolean...

Sounds great.  I would've gone with bool but I found a few places using nsresult instead of bool (e.g. TransactionThreadPool::GetOrCreate) and I thought it might be a style thing.

Everything else fixed; thanks!
Comment 7 User image Luke Wagner [:luke] 2011-07-29 14:53:47 PDT

I just realized I pushed without waiting for the answer to my question in comment 6.  If the answer is not 'yes', I can change it.
Comment 8 User image Ben Turner (not reading bugmail, use the needinfo flag!) 2011-07-29 14:58:56 PDT
It's fine :)
Comment 9 User image Luke Wagner [:luke] 2011-07-29 15:28:53 PDT
Comment 10 User image Marco Bonardo [::mak] 2011-08-01 01:47:41 PDT
backed out due to Trace Malloc Leaks increase 1.61% on MacOSX 10.5.2. Perf-o-matic seems to clearly point at this changeset.
If this is expected or we are fine ignoring it, please repush specifying that.
Comment 11 User image Luke Wagner [:luke] 2011-08-01 12:20:24 PDT
Marco, could I ask you a few basic questions:

By "Trace Malloc Leaks", do you mean the "LK: " number that shows up on TBPL for the "leak test build"?  I see this number hopping between 1.86MB and 1.89MB before and after the backed-out cset.  Is this what is being measured?

As an experiment, I put an abort() in the code I changed (which requires special indexedDB use to exercise) and ran:
  python -- --trace-malloc malloc.log --shutdown-leaks=sdleak.log
and the abort() wasn't hit.  Is that the right test to look at?

Lastly, mochitest-2 actually runs the tests which exercise this code, but looking at the processLeakLog() line in the logs doesn't report any leak nor does it appear to push any results to any graph server, so I don't think that's what this is about.
Comment 12 User image Luke Wagner [:luke] 2011-08-01 12:29:03 PDT
So I also looked at the perftastic graph in question:[[28,63,1287]]&sel=1311813637,1312202719

I do see it going from bouncing up and down to staying at the high level exactly at this patch's landing.  However, I see it going back to bouncing around well before the backout cset (f4415470040a).

I'll wait a day and see if anyone rejects, but I'm inclined to go with "ignore and reland".
Comment 13 User image Marco Bonardo [::mak] 2011-08-01 12:56:53 PDT
Unfortunately I don't know the internals of all of our Talos tests that well, you may try pinging anode to get those. I'm not sure about the level of trust we have in this measure, especially on OSX10.5, may be we may ignore this kind of small noise or even we did in the past, I'm not the right person to do that call.

I did the backout because while this measure IS noisy, before this patch it was most of the time on the lower bound, and sometimes on the upper bound. After this patch that was inverted and was mostly on the upper bound. See (I suggest you to use the new graph server, is so much faster)[[28,63,7]]&sel=1311952647785.9873,1312228051837&displayrange=7&datatype=running

Since there was a lot of backlog on inbound, and you were not around to ask if some sort of regressions was expected at that time, I preferred going the safe way.  After the backout this is still noisy as before, but I see more runs at the lower bound.
Comment 14 User image Luke Wagner [:luke] 2011-08-01 14:46:42 PDT
Marco, thanks for your help on this and with inbound in general.  Wow, graphs-new is faster.

On more recent csets (after the backout), I'm still seeing a tendency to the high bound.  Based on this, above evidence and talking to bent and khuey, I'm going to reland the patch as is but, as bent suggested, with MOZ_COUNT_CTOR/DTOR added to ThreadLocalJSRuntime for good measure.
Comment 16 User image Marco Bonardo [::mak] 2011-08-02 03:24:45 PDT

Note You need to log in before you can comment on or make changes to this bug.