Optimize switch() with string labels

NEW
Unassigned

Status

()

enhancement
7 years ago
5 years ago

People

(Reporter: Yoric, Unassigned)

Tracking

({perf})

Firefox Tracking Flags

(Not tracked)

Details

(URL)

I have the impression that many frameworks out there use the following pattern:

var MyTags = {
   Tag1: "Tag1",
   Tag2: "Tag2",
   // ... many more
}

switch(myValue.flag) {
  case MyTags.Tag1: ...
  case MyTags.Tag2: ...
  // ...
  default:
  // ...
}

From what I understand, at the moment, on SpiderMonkey, this switch is implemented naively (as a sequence of string comparisons), which is quite expensive. I believe that we can do much better.

Attaching as URL the source code of one such library.
I assume that the most common scenario is the following:
- the shape of MyTags doesn't change;
- none of the values of MyTags changes.

As long as these invariants hold, the code is very similar to the following:


// Object can be pre-allocated or allocated dynamically and cached
const mySwitch = {
  _Tag1: function() {
    // ...
    // may need to branch to other methods,
    // depending on break
  },
  _Tag2: function() {
    // ...
  },
  default: function() {
    // ...
  }
};

let branch = mySwitch['_'+myValue.flag] || mySwitch.default;
let action = branch();

if (action) { // Handle any |return| from a branch
  return action._return;
}

The code is not meant to be 100% exact, just to suggest a strategy that brings the cost down to one fast logarithmic lookup, without complicating the VM.
Keywords: perf
Assignee: general → nobody
You need to log in before you can comment on or make changes to this bug.