简体   繁体   中英

Performance if (typeof x == 'number')?

I've been Googling quite some time for eg 'typeof' and 'performance', but I haven't been able to find a satisfactory answer to the following problem.

I am trying to implement complex numbers for the Transcrypt Python to JavaScript compiler, using local operator overloading. Since we're dealing with a dynamically typed language, it cannot be predicted what type of data will be in a variable.

If I translate x + y to JavaScript, having operator overloading switched on, it will translate eg as __add__ (x, y) In order to do the right thing, the __add__ function has to check for both x and y whether they are 'ordinary' JavaScript numbers or if one of them or both of them are of type 'complex', since that requires special operations.

The most obvious way to do that is to test for typeof x == 'number' . However, coming from a C/C++ background, it seems ridiculously inefficient to test for equality with a string with six characters which on top of that first has to be retrieved from memory, only to possible add two integers, which for many processors, once parsed, would be only one instruction.

What amazes me most is that checks like this are advised everywhere around the internet as the normal thing to do. Does anyone know if x == 'number' or possible x === 'number' is somehow cleverly optimized to prevent a full string comparison.

To further clarify the problem, here's my current code for the __add__ operator, using the string comparison.

def __add__ (self, other):
    if __typeof__ (other) == 'number':   # Translates to: if (typeof other == 'number') {
        return complex (self.real + other, self.imag)
    else:   # Other is complex
        return complex (self.real + other.real, self.imag + other.imag)

If not can anyone hint me on a quicker way to distinguish between a number and an arbitrary non-numerical object.

Thanks for the tips. The source is now:

def __sub__ (self, other):
    if __typeof__ (other, 'number'):
        return complex (self.real - other, self.imag)
    else:
        return complex (self.real - other.real, self.imag - other.imag)

translated by:

elif node.func.id == '__typeof__':
    self.emit ('typeof ')
    self.visit (node.args [0])
    self.emit (' === ') # Give JavaScript string interning a chance to avoid char by char comparison
    self.visit (node.args [1])
    return

to:

get __add__ () {return __get__ (this, function (self, other) {
    if (typeof other === 'number') {
        return complex (self.real + other, self.imag);
    }
    else {
        return complex (self.real + other.real, self.imag + other.imag);
    }
});},

That depends on the JavaScript engine. But a typeof obj can only return a fixed set of strings. So a compiler/engine can optimize a typeof obj === 'number' into a test that does not do a string comparison, but uses a more efficient test.

The byte code V8 created for if( typeof obj === 'number' ) will be something like this:

268 S> 0x24110cfe4b0 @   62 : 13 04     LdaImmutableCurrentContextSlot [4]
       0x24110cfe4b2 @   64 : 65 00     TestTypeOf #0
       0x24110cfe4b4 @   66 : 86 16     JumpIfFalse [22] (0x24110cfe4ca @ 88)

So at least v8 does in fact have an own command to test if an object is of a certain type, which is not a string comparison.

I don't know if this is true for the other engines, but it is likely that they do the same thing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM