├── LICENSE ├── README.md ├── benchmark.js ├── chromium-memory.png ├── index.html ├── indexof-vs-regexp.html ├── lodash.js ├── platform.js ├── set-vs-regexp.html └── tokenize-to-str-vs-to-int.html /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # obj-vs-set-vs-map 2 | Just a benchmark to measure performance of `Set()`, `Map()` versus `Object.create(null)`. 3 | 4 | Run the benchmark for your current browser: . 5 | 6 | ### Example of results 7 | 8 | Chromium v51: 9 | 10 | - Adding items: 11 | - `Obj set() x 27.38 ops/sec ±6.75% (50 runs sampled)` 12 | - `Set set() x 83.31 ops/sec ±3.47% (70 runs sampled)` 13 | - `Map set() x 68.24 ops/sec ±3.12% (69 runs sampled)` 14 | - Looking up items (80% misses): 15 | - `Obj get() x 10,516 ops/sec ±0.30% (93 runs sampled)` 16 | - `Set get() x 17,429 ops/sec ±0.51% (94 runs sampled)` 17 | - `Map get() x 15,462 ops/sec ±0.35% (96 runs sampled)` 18 | 19 | -------------------------------------------------------------------------------- /chromium-memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorhill/obj-vs-set-vs-map/868ee1ea51d4c64c7570d85d39886aafeb40fdf7/chromium-memory.png -------------------------------------------------------------------------------- /indexof-vs-regexp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Benchmark: String.indexOf() vs RegExp.test()

8 |

9 |
10 |
11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /platform.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Platform.js 3 | * Copyright 2014-2016 Benjamin Tan 4 | * Copyright 2011-2013 John-David Dalton 5 | * Available under MIT license 6 | */ 7 | ;(function() { 8 | 'use strict'; 9 | 10 | /** Used to determine if values are of the language type `Object`. */ 11 | var objectTypes = { 12 | 'function': true, 13 | 'object': true 14 | }; 15 | 16 | /** Used as a reference to the global object. */ 17 | var root = (objectTypes[typeof window] && window) || this; 18 | 19 | /** Backup possible global object. */ 20 | var oldRoot = root; 21 | 22 | /** Detect free variable `exports`. */ 23 | var freeExports = objectTypes[typeof exports] && exports; 24 | 25 | /** Detect free variable `module`. */ 26 | var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; 27 | 28 | /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ 29 | var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; 30 | if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { 31 | root = freeGlobal; 32 | } 33 | 34 | /** 35 | * Used as the maximum length of an array-like object. 36 | * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) 37 | * for more details. 38 | */ 39 | var maxSafeInteger = Math.pow(2, 53) - 1; 40 | 41 | /** Regular expression to detect Opera. */ 42 | var reOpera = /\bOpera/; 43 | 44 | /** Possible global object. */ 45 | var thisBinding = this; 46 | 47 | /** Used for native method references. */ 48 | var objectProto = Object.prototype; 49 | 50 | /** Used to check for own properties of an object. */ 51 | var hasOwnProperty = objectProto.hasOwnProperty; 52 | 53 | /** Used to resolve the internal `[[Class]]` of values. */ 54 | var toString = objectProto.toString; 55 | 56 | /*--------------------------------------------------------------------------*/ 57 | 58 | /** 59 | * Capitalizes a string value. 60 | * 61 | * @private 62 | * @param {string} string The string to capitalize. 63 | * @returns {string} The capitalized string. 64 | */ 65 | function capitalize(string) { 66 | string = String(string); 67 | return string.charAt(0).toUpperCase() + string.slice(1); 68 | } 69 | 70 | /** 71 | * A utility function to clean up the OS name. 72 | * 73 | * @private 74 | * @param {string} os The OS name to clean up. 75 | * @param {string} [pattern] A `RegExp` pattern matching the OS name. 76 | * @param {string} [label] A label for the OS. 77 | */ 78 | function cleanupOS(os, pattern, label) { 79 | // Platform tokens are defined at: 80 | // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx 81 | // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx 82 | var data = { 83 | '10.0': '10', 84 | '6.4': '10 Technical Preview', 85 | '6.3': '8.1', 86 | '6.2': '8', 87 | '6.1': '7 / Server 2008 R2', 88 | '6.0': 'Vista / Server 2008', 89 | '5.2': 'XP 64-bit / Server 2003', 90 | '5.1': 'XP', 91 | '5.01': '2000 SP1', 92 | '5.0': '2000', 93 | '4.0': 'NT', 94 | '4.90': 'ME' 95 | }; 96 | // Detect Windows version from platform tokens. 97 | if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && 98 | (data = data[/[\d.]+$/.exec(os)])) { 99 | os = 'Windows ' + data; 100 | } 101 | // Correct character case and cleanup string. 102 | os = String(os); 103 | 104 | if (pattern && label) { 105 | os = os.replace(RegExp(pattern, 'i'), label); 106 | } 107 | 108 | os = format( 109 | os.replace(/ ce$/i, ' CE') 110 | .replace(/\bhpw/i, 'web') 111 | .replace(/\bMacintosh\b/, 'Mac OS') 112 | .replace(/_PowerPC\b/i, ' OS') 113 | .replace(/\b(OS X) [^ \d]+/i, '$1') 114 | .replace(/\bMac (OS X)\b/, '$1') 115 | .replace(/\/(\d)/, ' $1') 116 | .replace(/_/g, '.') 117 | .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') 118 | .replace(/\bx86\.64\b/gi, 'x86_64') 119 | .replace(/\b(Windows Phone) OS\b/, '$1') 120 | .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') 121 | .split(' on ')[0] 122 | ); 123 | 124 | return os; 125 | } 126 | 127 | /** 128 | * An iteration utility for arrays and objects. 129 | * 130 | * @private 131 | * @param {Array|Object} object The object to iterate over. 132 | * @param {Function} callback The function called per iteration. 133 | */ 134 | function each(object, callback) { 135 | var index = -1, 136 | length = object ? object.length : 0; 137 | 138 | if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { 139 | while (++index < length) { 140 | callback(object[index], index, object); 141 | } 142 | } else { 143 | forOwn(object, callback); 144 | } 145 | } 146 | 147 | /** 148 | * Trim and conditionally capitalize string values. 149 | * 150 | * @private 151 | * @param {string} string The string to format. 152 | * @returns {string} The formatted string. 153 | */ 154 | function format(string) { 155 | string = trim(string); 156 | return /^(?:webOS|i(?:OS|P))/.test(string) 157 | ? string 158 | : capitalize(string); 159 | } 160 | 161 | /** 162 | * Iterates over an object's own properties, executing the `callback` for each. 163 | * 164 | * @private 165 | * @param {Object} object The object to iterate over. 166 | * @param {Function} callback The function executed per own property. 167 | */ 168 | function forOwn(object, callback) { 169 | for (var key in object) { 170 | if (hasOwnProperty.call(object, key)) { 171 | callback(object[key], key, object); 172 | } 173 | } 174 | } 175 | 176 | /** 177 | * Gets the internal `[[Class]]` of a value. 178 | * 179 | * @private 180 | * @param {*} value The value. 181 | * @returns {string} The `[[Class]]`. 182 | */ 183 | function getClassOf(value) { 184 | return value == null 185 | ? capitalize(value) 186 | : toString.call(value).slice(8, -1); 187 | } 188 | 189 | /** 190 | * Host objects can return type values that are different from their actual 191 | * data type. The objects we are concerned with usually return non-primitive 192 | * types of "object", "function", or "unknown". 193 | * 194 | * @private 195 | * @param {*} object The owner of the property. 196 | * @param {string} property The property to check. 197 | * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. 198 | */ 199 | function isHostType(object, property) { 200 | var type = object != null ? typeof object[property] : 'number'; 201 | return !/^(?:boolean|number|string|undefined)$/.test(type) && 202 | (type == 'object' ? !!object[property] : true); 203 | } 204 | 205 | /** 206 | * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. 207 | * 208 | * @private 209 | * @param {string} string The string to qualify. 210 | * @returns {string} The qualified string. 211 | */ 212 | function qualify(string) { 213 | return String(string).replace(/([ -])(?!$)/g, '$1?'); 214 | } 215 | 216 | /** 217 | * A bare-bones `Array#reduce` like utility function. 218 | * 219 | * @private 220 | * @param {Array} array The array to iterate over. 221 | * @param {Function} callback The function called per iteration. 222 | * @returns {*} The accumulated result. 223 | */ 224 | function reduce(array, callback) { 225 | var accumulator = null; 226 | each(array, function(value, index) { 227 | accumulator = callback(accumulator, value, index, array); 228 | }); 229 | return accumulator; 230 | } 231 | 232 | /** 233 | * Removes leading and trailing whitespace from a string. 234 | * 235 | * @private 236 | * @param {string} string The string to trim. 237 | * @returns {string} The trimmed string. 238 | */ 239 | function trim(string) { 240 | return String(string).replace(/^ +| +$/g, ''); 241 | } 242 | 243 | /*--------------------------------------------------------------------------*/ 244 | 245 | /** 246 | * Creates a new platform object. 247 | * 248 | * @memberOf platform 249 | * @param {Object|string} [ua=navigator.userAgent] The user agent string or 250 | * context object. 251 | * @returns {Object} A platform object. 252 | */ 253 | function parse(ua) { 254 | 255 | /** The environment context object. */ 256 | var context = root; 257 | 258 | /** Used to flag when a custom context is provided. */ 259 | var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; 260 | 261 | // Juggle arguments. 262 | if (isCustomContext) { 263 | context = ua; 264 | ua = null; 265 | } 266 | 267 | /** Browser navigator object. */ 268 | var nav = context.navigator || {}; 269 | 270 | /** Browser user agent string. */ 271 | var userAgent = nav.userAgent || ''; 272 | 273 | ua || (ua = userAgent); 274 | 275 | /** Used to flag when `thisBinding` is the [ModuleScope]. */ 276 | var isModuleScope = isCustomContext || thisBinding == oldRoot; 277 | 278 | /** Used to detect if browser is like Chrome. */ 279 | var likeChrome = isCustomContext 280 | ? !!nav.likeChrome 281 | : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); 282 | 283 | /** Internal `[[Class]]` value shortcuts. */ 284 | var objectClass = 'Object', 285 | airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', 286 | enviroClass = isCustomContext ? objectClass : 'Environment', 287 | javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), 288 | phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; 289 | 290 | /** Detect Java environments. */ 291 | var java = /\bJava/.test(javaClass) && context.java; 292 | 293 | /** Detect Rhino. */ 294 | var rhino = java && getClassOf(context.environment) == enviroClass; 295 | 296 | /** A character to represent alpha. */ 297 | var alpha = java ? 'a' : '\u03b1'; 298 | 299 | /** A character to represent beta. */ 300 | var beta = java ? 'b' : '\u03b2'; 301 | 302 | /** Browser document object. */ 303 | var doc = context.document || {}; 304 | 305 | /** 306 | * Detect Opera browser (Presto-based). 307 | * http://www.howtocreate.co.uk/operaStuff/operaObject.html 308 | * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini 309 | */ 310 | var opera = context.operamini || context.opera; 311 | 312 | /** Opera `[[Class]]`. */ 313 | var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) 314 | ? operaClass 315 | : (opera = null); 316 | 317 | /*------------------------------------------------------------------------*/ 318 | 319 | /** Temporary variable used over the script's lifetime. */ 320 | var data; 321 | 322 | /** The CPU architecture. */ 323 | var arch = ua; 324 | 325 | /** Platform description array. */ 326 | var description = []; 327 | 328 | /** Platform alpha/beta indicator. */ 329 | var prerelease = null; 330 | 331 | /** A flag to indicate that environment features should be used to resolve the platform. */ 332 | var useFeatures = ua == userAgent; 333 | 334 | /** The browser/environment version. */ 335 | var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); 336 | 337 | /** A flag to indicate if the OS begins with "Name Version /". */ 338 | var isSpecialCasedOS; 339 | 340 | /* Detectable layout engines (order is important). */ 341 | var layout = getLayout([ 342 | { 'label': 'EdgeHTML', 'pattern': 'Edge' }, 343 | 'Trident', 344 | { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, 345 | 'iCab', 346 | 'Presto', 347 | 'NetFront', 348 | 'Tasman', 349 | 'KHTML', 350 | 'Gecko' 351 | ]); 352 | 353 | /* Detectable browser names (order is important). */ 354 | var name = getName([ 355 | 'Adobe AIR', 356 | 'Arora', 357 | 'Avant Browser', 358 | 'Breach', 359 | 'Camino', 360 | 'Epiphany', 361 | 'Fennec', 362 | 'Flock', 363 | 'Galeon', 364 | 'GreenBrowser', 365 | 'iCab', 366 | 'Iceweasel', 367 | 'K-Meleon', 368 | 'Konqueror', 369 | 'Lunascape', 370 | 'Maxthon', 371 | { 'label': 'Microsoft Edge', 'pattern': 'Edge' }, 372 | 'Midori', 373 | 'Nook Browser', 374 | 'PaleMoon', 375 | 'PhantomJS', 376 | 'Raven', 377 | 'Rekonq', 378 | 'RockMelt', 379 | 'SeaMonkey', 380 | { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, 381 | 'Sleipnir', 382 | 'SlimBrowser', 383 | { 'label': 'SRWare Iron', 'pattern': 'Iron' }, 384 | 'Sunrise', 385 | 'Swiftfox', 386 | 'WebPositive', 387 | 'Opera Mini', 388 | { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, 389 | 'Opera', 390 | { 'label': 'Opera', 'pattern': 'OPR' }, 391 | 'Chrome', 392 | { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, 393 | { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, 394 | { 'label': 'Firefox Mobile', 'pattern': 'FxiOS' }, 395 | { 'label': 'IE', 'pattern': 'IEMobile' }, 396 | { 'label': 'IE', 'pattern': 'MSIE' }, 397 | 'Safari' 398 | ]); 399 | 400 | /* Detectable products (order is important). */ 401 | var product = getProduct([ 402 | { 'label': 'BlackBerry', 'pattern': 'BB10' }, 403 | 'BlackBerry', 404 | { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, 405 | { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, 406 | { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, 407 | { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, 408 | 'Google TV', 409 | 'Lumia', 410 | 'iPad', 411 | 'iPod', 412 | 'iPhone', 413 | 'Kindle', 414 | { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, 415 | 'Nexus', 416 | 'Nook', 417 | 'PlayBook', 418 | 'PlayStation 3', 419 | 'PlayStation 4', 420 | 'PlayStation Vita', 421 | 'TouchPad', 422 | 'Transformer', 423 | { 'label': 'Wii U', 'pattern': 'WiiU' }, 424 | 'Wii', 425 | 'Xbox One', 426 | { 'label': 'Xbox 360', 'pattern': 'Xbox' }, 427 | 'Xoom' 428 | ]); 429 | 430 | /* Detectable manufacturers. */ 431 | var manufacturer = getManufacturer({ 432 | 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, 433 | 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, 434 | 'Asus': { 'Transformer': 1 }, 435 | 'Barnes & Noble': { 'Nook': 1 }, 436 | 'BlackBerry': { 'PlayBook': 1 }, 437 | 'Google': { 'Google TV': 1, 'Nexus': 1 }, 438 | 'HP': { 'TouchPad': 1 }, 439 | 'HTC': {}, 440 | 'LG': {}, 441 | 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, 442 | 'Motorola': { 'Xoom': 1 }, 443 | 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, 444 | 'Nokia': { 'Lumia': 1 }, 445 | 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, 446 | 'Sony': { 'PlayStation 4': 1, 'PlayStation 3': 1, 'PlayStation Vita': 1 } 447 | }); 448 | 449 | /* Detectable operating systems (order is important). */ 450 | var os = getOS([ 451 | 'Windows Phone ', 452 | 'Android', 453 | 'CentOS', 454 | { 'label': 'Chrome OS', 'pattern': 'CrOS' }, 455 | 'Debian', 456 | 'Fedora', 457 | 'FreeBSD', 458 | 'Gentoo', 459 | 'Haiku', 460 | 'Kubuntu', 461 | 'Linux Mint', 462 | 'OpenBSD', 463 | 'Red Hat', 464 | 'SuSE', 465 | 'Ubuntu', 466 | 'Xubuntu', 467 | 'Cygwin', 468 | 'Symbian OS', 469 | 'hpwOS', 470 | 'webOS ', 471 | 'webOS', 472 | 'Tablet OS', 473 | 'Linux', 474 | 'Mac OS X', 475 | 'Macintosh', 476 | 'Mac', 477 | 'Windows 98;', 478 | 'Windows ' 479 | ]); 480 | 481 | /*------------------------------------------------------------------------*/ 482 | 483 | /** 484 | * Picks the layout engine from an array of guesses. 485 | * 486 | * @private 487 | * @param {Array} guesses An array of guesses. 488 | * @returns {null|string} The detected layout engine. 489 | */ 490 | function getLayout(guesses) { 491 | return reduce(guesses, function(result, guess) { 492 | return result || RegExp('\\b' + ( 493 | guess.pattern || qualify(guess) 494 | ) + '\\b', 'i').exec(ua) && (guess.label || guess); 495 | }); 496 | } 497 | 498 | /** 499 | * Picks the manufacturer from an array of guesses. 500 | * 501 | * @private 502 | * @param {Array} guesses An object of guesses. 503 | * @returns {null|string} The detected manufacturer. 504 | */ 505 | function getManufacturer(guesses) { 506 | return reduce(guesses, function(result, value, key) { 507 | // Lookup the manufacturer by product or scan the UA for the manufacturer. 508 | return result || ( 509 | value[product] || 510 | value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || 511 | RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) 512 | ) && key; 513 | }); 514 | } 515 | 516 | /** 517 | * Picks the browser name from an array of guesses. 518 | * 519 | * @private 520 | * @param {Array} guesses An array of guesses. 521 | * @returns {null|string} The detected browser name. 522 | */ 523 | function getName(guesses) { 524 | return reduce(guesses, function(result, guess) { 525 | return result || RegExp('\\b' + ( 526 | guess.pattern || qualify(guess) 527 | ) + '\\b', 'i').exec(ua) && (guess.label || guess); 528 | }); 529 | } 530 | 531 | /** 532 | * Picks the OS name from an array of guesses. 533 | * 534 | * @private 535 | * @param {Array} guesses An array of guesses. 536 | * @returns {null|string} The detected OS name. 537 | */ 538 | function getOS(guesses) { 539 | return reduce(guesses, function(result, guess) { 540 | var pattern = guess.pattern || qualify(guess); 541 | if (!result && (result = 542 | RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) 543 | )) { 544 | result = cleanupOS(result, pattern, guess.label || guess); 545 | } 546 | return result; 547 | }); 548 | } 549 | 550 | /** 551 | * Picks the product name from an array of guesses. 552 | * 553 | * @private 554 | * @param {Array} guesses An array of guesses. 555 | * @returns {null|string} The detected product name. 556 | */ 557 | function getProduct(guesses) { 558 | return reduce(guesses, function(result, guess) { 559 | var pattern = guess.pattern || qualify(guess); 560 | if (!result && (result = 561 | RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || 562 | RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) 563 | )) { 564 | // Split by forward slash and append product version if needed. 565 | if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { 566 | result[0] += ' ' + result[1]; 567 | } 568 | // Correct character case and cleanup string. 569 | guess = guess.label || guess; 570 | result = format(result[0] 571 | .replace(RegExp(pattern, 'i'), guess) 572 | .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') 573 | .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); 574 | } 575 | return result; 576 | }); 577 | } 578 | 579 | /** 580 | * Resolves the version using an array of UA patterns. 581 | * 582 | * @private 583 | * @param {Array} patterns An array of UA patterns. 584 | * @returns {null|string} The detected version. 585 | */ 586 | function getVersion(patterns) { 587 | return reduce(patterns, function(result, pattern) { 588 | return result || (RegExp(pattern + 589 | '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; 590 | }); 591 | } 592 | 593 | /** 594 | * Returns `platform.description` when the platform object is coerced to a string. 595 | * 596 | * @name toString 597 | * @memberOf platform 598 | * @returns {string} Returns `platform.description` if available, else an empty string. 599 | */ 600 | function toStringPlatform() { 601 | return this.description || ''; 602 | } 603 | 604 | /*------------------------------------------------------------------------*/ 605 | 606 | // Convert layout to an array so we can add extra details. 607 | layout && (layout = [layout]); 608 | 609 | // Detect product names that contain their manufacturer's name. 610 | if (manufacturer && !product) { 611 | product = getProduct([manufacturer]); 612 | } 613 | // Clean up Google TV. 614 | if ((data = /\bGoogle TV\b/.exec(product))) { 615 | product = data[0]; 616 | } 617 | // Detect simulators. 618 | if (/\bSimulator\b/i.test(ua)) { 619 | product = (product ? product + ' ' : '') + 'Simulator'; 620 | } 621 | // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. 622 | if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { 623 | description.push('running in Turbo/Uncompressed mode'); 624 | } 625 | // Detect iOS. 626 | if (/^iP/.test(product)) { 627 | name || (name = 'Safari'); 628 | os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) 629 | ? ' ' + data[1].replace(/_/g, '.') 630 | : ''); 631 | } 632 | // Detect Kubuntu. 633 | else if (name == 'Konqueror' && !/buntu/i.test(os)) { 634 | os = 'Kubuntu'; 635 | } 636 | // Detect Android browsers. 637 | else if (manufacturer && manufacturer != 'Google' && 638 | ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) { 639 | name = 'Android Browser'; 640 | os = /\bAndroid\b/.test(os) ? os : 'Android'; 641 | } 642 | // Detect Silk desktop/accelerated modes. 643 | else if (name == 'Silk') { 644 | if (!/\bMobi/i.test(ua)) { 645 | os = 'Android'; 646 | description.unshift('desktop mode'); 647 | } 648 | if (/Accelerated *= *true/i.test(ua)) { 649 | description.unshift('accelerated'); 650 | } 651 | } 652 | // Detect PaleMoon identifying as Firefox. 653 | else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { 654 | description.push('identifying as Firefox ' + data[1]); 655 | } 656 | // Detect Firefox OS and products running Firefox. 657 | else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { 658 | os || (os = 'Firefox OS'); 659 | product || (product = data[1]); 660 | } 661 | // Detect false positives for Firefox/Safari. 662 | else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { 663 | // Escape the `/` for Firefox 1. 664 | if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { 665 | // Clear name of false positives. 666 | name = null; 667 | } 668 | // Reassign a generic name. 669 | if ((data = product || manufacturer || os) && 670 | (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { 671 | name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; 672 | } 673 | } 674 | // Detect non-Opera (Presto-based) versions (order is important). 675 | if (!version) { 676 | version = getVersion([ 677 | '(?:Cloud9|CriOS|CrMo|Edge|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|Silk(?!/[\\d.]+$))', 678 | 'Version', 679 | qualify(name), 680 | '(?:Firefox|Minefield|NetFront)' 681 | ]); 682 | } 683 | // Detect stubborn layout engines. 684 | if ((data = 685 | layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || 686 | /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || 687 | /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || 688 | !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || 689 | layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' 690 | )) { 691 | layout = [data]; 692 | } 693 | // Detect Windows Phone 7 desktop mode. 694 | if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { 695 | name += ' Mobile'; 696 | os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); 697 | description.unshift('desktop mode'); 698 | } 699 | // Detect Windows Phone 8.x desktop mode. 700 | else if (/\bWPDesktop\b/i.test(ua)) { 701 | name = 'IE Mobile'; 702 | os = 'Windows Phone 8.x'; 703 | description.unshift('desktop mode'); 704 | version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); 705 | } 706 | // Detect IE 11. 707 | else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { 708 | if (name) { 709 | description.push('identifying as ' + name + (version ? ' ' + version : '')); 710 | } 711 | name = 'IE'; 712 | version = data[1]; 713 | } 714 | // Leverage environment features. 715 | if (useFeatures) { 716 | // Detect server-side environments. 717 | // Rhino has a global function while others have a global object. 718 | if (isHostType(context, 'global')) { 719 | if (java) { 720 | data = java.lang.System; 721 | arch = data.getProperty('os.arch'); 722 | os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); 723 | } 724 | if (isModuleScope && isHostType(context, 'system') && (data = [context.system])[0]) { 725 | os || (os = data[0].os || null); 726 | try { 727 | data[1] = context.require('ringo/engine').version; 728 | version = data[1].join('.'); 729 | name = 'RingoJS'; 730 | } catch(e) { 731 | if (data[0].global.system == context.system) { 732 | name = 'Narwhal'; 733 | } 734 | } 735 | } 736 | else if (typeof context.process == 'object' && (data = context.process)) { 737 | name = 'Node.js'; 738 | arch = data.arch; 739 | os = data.platform; 740 | version = /[\d.]+/.exec(data.version)[0]; 741 | } 742 | else if (rhino) { 743 | name = 'Rhino'; 744 | } 745 | } 746 | // Detect Adobe AIR. 747 | else if (getClassOf((data = context.runtime)) == airRuntimeClass) { 748 | name = 'Adobe AIR'; 749 | os = data.flash.system.Capabilities.os; 750 | } 751 | // Detect PhantomJS. 752 | else if (getClassOf((data = context.phantom)) == phantomClass) { 753 | name = 'PhantomJS'; 754 | version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); 755 | } 756 | // Detect IE compatibility modes. 757 | else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { 758 | // We're in compatibility mode when the Trident version + 4 doesn't 759 | // equal the document mode. 760 | version = [version, doc.documentMode]; 761 | if ((data = +data[1] + 4) != version[1]) { 762 | description.push('IE ' + version[1] + ' mode'); 763 | layout && (layout[1] = ''); 764 | version[1] = data; 765 | } 766 | version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; 767 | } 768 | os = os && format(os); 769 | } 770 | // Detect prerelease phases. 771 | if (version && (data = 772 | /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || 773 | /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || 774 | /\bMinefield\b/i.test(ua) && 'a' 775 | )) { 776 | prerelease = /b/i.test(data) ? 'beta' : 'alpha'; 777 | version = version.replace(RegExp(data + '\\+?$'), '') + 778 | (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); 779 | } 780 | // Detect Firefox Mobile. 781 | if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) { 782 | name = 'Firefox Mobile'; 783 | } 784 | // Obscure Maxthon's unreliable version. 785 | else if (name == 'Maxthon' && version) { 786 | version = version.replace(/\.[\d.]+/, '.x'); 787 | } 788 | // Detect Xbox 360 and Xbox One. 789 | else if (/\bXbox\b/i.test(product)) { 790 | os = null; 791 | if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { 792 | description.unshift('mobile mode'); 793 | } 794 | } 795 | // Add mobile postfix. 796 | else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && 797 | (os == 'Windows CE' || /Mobi/i.test(ua))) { 798 | name += ' Mobile'; 799 | } 800 | // Detect IE platform preview. 801 | else if (name == 'IE' && useFeatures && context.external === null) { 802 | description.unshift('platform preview'); 803 | } 804 | // Detect BlackBerry OS version. 805 | // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp 806 | else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = 807 | (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || 808 | version 809 | )) { 810 | data = [data, /BB10/.test(ua)]; 811 | os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; 812 | version = null; 813 | } 814 | // Detect Opera identifying/masking itself as another browser. 815 | // http://www.opera.com/support/kb/view/843/ 816 | else if (this != forOwn && product != 'Wii' && ( 817 | (useFeatures && opera) || 818 | (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || 819 | (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || 820 | (name == 'IE' && ( 821 | (os && !/^Win/.test(os) && version > 5.5) || 822 | /\bWindows XP\b/.test(os) && version > 8 || 823 | version == 8 && !/\bTrident\b/.test(ua) 824 | )) 825 | ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { 826 | // When "identifying", the UA contains both Opera and the other browser's name. 827 | data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); 828 | if (reOpera.test(name)) { 829 | if (/\bIE\b/.test(data) && os == 'Mac OS') { 830 | os = null; 831 | } 832 | data = 'identify' + data; 833 | } 834 | // When "masking", the UA contains only the other browser's name. 835 | else { 836 | data = 'mask' + data; 837 | if (operaClass) { 838 | name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); 839 | } else { 840 | name = 'Opera'; 841 | } 842 | if (/\bIE\b/.test(data)) { 843 | os = null; 844 | } 845 | if (!useFeatures) { 846 | version = null; 847 | } 848 | } 849 | layout = ['Presto']; 850 | description.push(data); 851 | } 852 | // Detect WebKit Nightly and approximate Chrome/Safari versions. 853 | if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { 854 | // Correct build number for numeric comparison. 855 | // (e.g. "532.5" becomes "532.05") 856 | data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; 857 | // Nightly builds are postfixed with a "+". 858 | if (name == 'Safari' && data[1].slice(-1) == '+') { 859 | name = 'WebKit Nightly'; 860 | prerelease = 'alpha'; 861 | version = data[1].slice(0, -1); 862 | } 863 | // Clear incorrect browser versions. 864 | else if (version == data[1] || 865 | version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { 866 | version = null; 867 | } 868 | // Use the full Chrome version when available. 869 | data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]; 870 | // Detect Blink layout engine. 871 | if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { 872 | layout = ['Blink']; 873 | } 874 | // Detect JavaScriptCore. 875 | // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi 876 | if (!useFeatures || (!likeChrome && !data[1])) { 877 | layout && (layout[1] = 'like Safari'); 878 | data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8'); 879 | } else { 880 | layout && (layout[1] = 'like Chrome'); 881 | data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); 882 | } 883 | // Add the postfix of ".x" or "+" for approximate versions. 884 | layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); 885 | // Obscure version for some Safari 1-2 releases. 886 | if (name == 'Safari' && (!version || parseInt(version) > 45)) { 887 | version = data; 888 | } 889 | } 890 | // Detect Opera desktop modes. 891 | if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { 892 | name += ' '; 893 | description.unshift('desktop mode'); 894 | if (data == 'zvav') { 895 | name += 'Mini'; 896 | version = null; 897 | } else { 898 | name += 'Mobile'; 899 | } 900 | os = os.replace(RegExp(' *' + data + '$'), ''); 901 | } 902 | // Detect Chrome desktop mode. 903 | else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { 904 | description.unshift('desktop mode'); 905 | name = 'Chrome Mobile'; 906 | version = null; 907 | 908 | if (/\bOS X\b/.test(os)) { 909 | manufacturer = 'Apple'; 910 | os = 'iOS 4.3+'; 911 | } else { 912 | os = null; 913 | } 914 | } 915 | // Strip incorrect OS versions. 916 | if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && 917 | ua.indexOf('/' + data + '-') > -1) { 918 | os = trim(os.replace(data, '')); 919 | } 920 | // Add layout engine. 921 | if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( 922 | /Browser|Lunascape|Maxthon/.test(name) || 923 | name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || 924 | /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) { 925 | // Don't add layout details to description if they are falsey. 926 | (data = layout[layout.length - 1]) && description.push(data); 927 | } 928 | // Combine contextual information. 929 | if (description.length) { 930 | description = ['(' + description.join('; ') + ')']; 931 | } 932 | // Append manufacturer to description. 933 | if (manufacturer && product && product.indexOf(manufacturer) < 0) { 934 | description.push('on ' + manufacturer); 935 | } 936 | // Append product to description. 937 | if (product) { 938 | description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); 939 | } 940 | // Parse the OS into an object. 941 | if (os) { 942 | data = 943 | / ([\d.+]+)$/.exec(os) || 944 | (isSpecialCasedOS = /^[a-z]+ ([\d.+]+) \//i.exec(os)); 945 | os = { 946 | 'architecture': 32, 947 | 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, 948 | 'version': data ? data[1] : null, 949 | 'toString': function() { 950 | var version = this.version; 951 | return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); 952 | } 953 | }; 954 | } 955 | // Add browser/OS architecture. 956 | if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { 957 | if (os) { 958 | os.architecture = 64; 959 | os.family = os.family.replace(RegExp(' *' + data), ''); 960 | } 961 | if ( 962 | name && (/\bWOW64\b/i.test(ua) || 963 | (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) 964 | ) { 965 | description.unshift('32-bit'); 966 | } 967 | } 968 | 969 | ua || (ua = null); 970 | 971 | /*------------------------------------------------------------------------*/ 972 | 973 | /** 974 | * The platform object. 975 | * 976 | * @name platform 977 | * @type Object 978 | */ 979 | var platform = {}; 980 | 981 | /** 982 | * The platform description. 983 | * 984 | * @memberOf platform 985 | * @type string|null 986 | */ 987 | platform.description = ua; 988 | 989 | /** 990 | * The name of the browser's layout engine. 991 | * 992 | * @memberOf platform 993 | * @type string|null 994 | */ 995 | platform.layout = layout && layout[0]; 996 | 997 | /** 998 | * The name of the product's manufacturer. 999 | * 1000 | * @memberOf platform 1001 | * @type string|null 1002 | */ 1003 | platform.manufacturer = manufacturer; 1004 | 1005 | /** 1006 | * The name of the browser/environment. 1007 | * 1008 | * @memberOf platform 1009 | * @type string|null 1010 | */ 1011 | platform.name = name; 1012 | 1013 | /** 1014 | * The alpha/beta release indicator. 1015 | * 1016 | * @memberOf platform 1017 | * @type string|null 1018 | */ 1019 | platform.prerelease = prerelease; 1020 | 1021 | /** 1022 | * The name of the product hosting the browser. 1023 | * 1024 | * @memberOf platform 1025 | * @type string|null 1026 | */ 1027 | platform.product = product; 1028 | 1029 | /** 1030 | * The browser's user agent string. 1031 | * 1032 | * @memberOf platform 1033 | * @type string|null 1034 | */ 1035 | platform.ua = ua; 1036 | 1037 | /** 1038 | * The browser/environment version. 1039 | * 1040 | * @memberOf platform 1041 | * @type string|null 1042 | */ 1043 | platform.version = name && version; 1044 | 1045 | /** 1046 | * The name of the operating system. 1047 | * 1048 | * @memberOf platform 1049 | * @type Object 1050 | */ 1051 | platform.os = os || { 1052 | 1053 | /** 1054 | * The CPU architecture the OS is built for. 1055 | * 1056 | * @memberOf platform.os 1057 | * @type number|null 1058 | */ 1059 | 'architecture': null, 1060 | 1061 | /** 1062 | * The family of the OS. 1063 | * 1064 | * Common values include: 1065 | * "Windows", "Windows 7 / Server 2008 R2", "Windows Vista / Server 2008", 1066 | * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE", 1067 | * "Android", "iOS" and "Windows Phone" 1068 | * 1069 | * @memberOf platform.os 1070 | * @type string|null 1071 | */ 1072 | 'family': null, 1073 | 1074 | /** 1075 | * The version of the OS. 1076 | * 1077 | * @memberOf platform.os 1078 | * @type string|null 1079 | */ 1080 | 'version': null, 1081 | 1082 | /** 1083 | * Returns the OS string. 1084 | * 1085 | * @memberOf platform.os 1086 | * @returns {string} The OS string. 1087 | */ 1088 | 'toString': function() { return 'null'; } 1089 | }; 1090 | 1091 | platform.parse = parse; 1092 | platform.toString = toStringPlatform; 1093 | 1094 | if (platform.version) { 1095 | description.unshift(version); 1096 | } 1097 | if (platform.name) { 1098 | description.unshift(name); 1099 | } 1100 | if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { 1101 | description.push(product ? '(' + os + ')' : 'on ' + os); 1102 | } 1103 | if (description.length) { 1104 | platform.description = description.join(' '); 1105 | } 1106 | return platform; 1107 | } 1108 | 1109 | /*--------------------------------------------------------------------------*/ 1110 | 1111 | // Export platform. 1112 | // Some AMD build optimizers, like r.js, check for condition patterns like the following: 1113 | if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { 1114 | // Define as an anonymous module so platform can be aliased through path mapping. 1115 | define(function() { 1116 | return parse(); 1117 | }); 1118 | } 1119 | // Check for `exports` after `define` in case a build optimizer adds an `exports` object. 1120 | else if (freeExports && freeModule) { 1121 | // Export for CommonJS support. 1122 | forOwn(parse(), function(value, key) { 1123 | freeExports[key] = value; 1124 | }); 1125 | } 1126 | else { 1127 | // Export to the global object. 1128 | root.platform = parse(); 1129 | } 1130 | }.call(this)); 1131 | -------------------------------------------------------------------------------- /set-vs-regexp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Benchmark: Set- vs RegExp- vs Trie-based dictionary of hostnames

8 |

9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 423 | 424 | 425 | -------------------------------------------------------------------------------- /tokenize-to-str-vs-to-int.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Benchmark: String-based tokens vs. integer-based tokens

8 |

The benchmark consists in the tokenization of a list of 350 URLs.

9 |

10 | Fork me on GitHub 11 |

stdout

12 |
13 | 14 | 15 | 16 | 17 | 136 | 137 | 489 | 490 | 491 | --------------------------------------------------------------------------------