What is the maximum length of a string in JavaScript? - javascript

I thought this would be an easy google search but nothing came up.
Say I create a loop that continually appends one character at a time to a variable.
At what point will the program crash?
I expect it will take <6 seconds for someone to comment "Why don't you try it and find out?", but trying it wouldn't tell me the answer to the question. Is it implementation-specific? Is it defined anywhere? It doesn't seem to be in the ECMAScript spec.
Are there any known limitations beyond available memory? Does performance degrade with strings holding Mbs or Gbs of text?
For the record, I did try running that loop....and it just crashed my browser :( Maybe if I make some adjustments and try again.

ECMAScript 2016 (ed. 7) established a maximum length of 2^53 - 1
elements. Previously, no maximum length was specified. In Firefox,
strings have a maximum length of 2**30 - 2 (~1GB).
In versions prior
to Firefox 65, the maximum length was 2**28- 1 (~256MB).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length

Related

Chrome usedJSHeapSize property

First of all, I've looked around the internet and found it quite badly documented.
Somewhere in my code I have a big memory leak that I'm trying to track and after using:
window.performance.memory.usedJSHeapSize
it looks like the value remains at the same level of 10MB, which is not true because when we compare to the values either visible here:
chrome://memory-internals/
or if we look at the Timeline in devTools we can see a big difference. Does anyone encountered a similar issue? Do I need to manually update these values (to run a command "update", "measure" etc?)
Following this topic:
Information heap size
it looks like this value is increased by a certain step, can we somehow see what is it or modify it? In my case from what I can see now the page has about 10MB, 30 minutes later there will be about 400MB, and half an hour after the page will crash..
Any ideas guys?
(Why the code is leaking it's a different issue, please treat this one as I was trying to use this variable to create some kind of test).
There's a section of the WebPlatform.org docs that explains this:
The values are quantized as to not expose private information to attackers. If Chrome is run with the flag --enable-precise-memory-info the values are not quantized.
http://docs.webplatform.org/wiki/apis/timing/properties/memory
So, by default, the number is not precise, and it only updates every 20 minutes! This should explain why your number doesn't change. If you use the flag, the number will be precise and current.
The WebKit commit message explains:
This patch adds an option to expose quantized and rate-limited memory
information to web pages. Web pages can only learn new data every 20
minutes, which helps mitigate attacks where the attacker compares two
readings to extract side-channel information. The patch also only
reports 100 distinct memory values, which (combined with the rate
limits) makes it difficult for attackers to learn about small changes in
memory use.

Why is Google Chrome's Math.random number generator not *that* random?

I ran into an odd "bug" today when I was running some unit tests in various browsers. I had run the tests in Firefox many times before today, and even IE but apparently not Chrome (v19-dev) yet. When I ran them in Chrome it consistently failed one test because two values I was calculating did not match.
When I really dug into what was happening I realized that the issue was that I was assuming that if I filled an array with 100,000 Math.random() values that they would all be unique (there wouldn't be any collisions). Turned out that in Chrome that is not true.
In Chrome I was consistently getting at least two pairs of values that matched out of 100,000. Firefox and IE9 never experience a collision. Here is a jsfiddle I wrote just for testing this that creates 1M Math.random() entries in an array: http://jsfiddle.net/pseudosavant/bcduj/
Does anyone know why the Chrome pseudo-random number generator that is used for Math.random is really not that random? It seems like this could have implications for any client-side js encryption routines that ever use Math.random.
Apparently Math.random() in V8 only works with 32 bit values (and didn't even correctly randomize all of those in the past). And with 32 bits, the probability of a collision reaches 50% around 2^16 = 65k values...
Other answers have explained the issue. If you're after better pseudo-random number generation in JavaScript, I'd recommend this page as a good place to start:
http://baagoe.com/en/RandomMusings/javascript/
I adapted one of the algorithms on this page for a script I'm using to generate UUIDs in the browser and had no collisions in my tests.
UPDATE 22 October 2013
The pages linked to above are no longer live. Here's a link to a snapshot from the Wayback Machine:
http://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/
And here's a link to a Node.js module that includes Alea.js:
https://npmjs.org/package/alea
See https://medium.com/#betable/tifu-by-using-math-random-f1c308c4fd9d:
If we analyze the first sub-generator independently we see that it has 32 bits of internal state. It’s not a full-cycle generator — its actual cycle length is about 590 million (18,030*2¹⁵-1, the math is tricky but it’s explained here and here, or you can just trust me). So we can only produce a maximum of 590 million distinct request identifiers with this generator. If they were randomly selected there would be a 50% chance of collision after generating just 30,000 identifiers.

How fast is parseFloat Vs. float ints in JavaScript?

I'm getting a huge dataset from a client's internal API. It'll contain a bunch of numerical data of prices such as: $31.23. He gives them to me as {"spend":"21.23"} which is fine, but I was concerned that after 1000+ items and running parseFloat() on all of those values (on top of graphing them) might be resource heavy on the client's browser.
Has anyone done this?
==Update==
I'm sorry. My question was too vague. My concern was that it's a string and i'm parsing it. My issue was is parseFloat faster than just an int. I.e. is appending parseFloat("12.12") to a div faster than simply just appending 12.12 and if so, how much faster.
On my work machine (Mac OS X, Intel 2 GHz Core i7), I saw the following results on jsperf.com:
Browser | parseFloat calls per second
----------------------------------------
Chrome 12 | 5.3 million
Firefox 6 | 21.7 million
IE 8 | 666.9 thousand <- totally unfair, ran on virtual machine
Opera 11 | 5.2 million
This is far from an exhaustive survey; but at a rough minimum of over 600 thousand calls per second (and that on a virtual machine), I think you should be good.
In regard for speed of parseFloat or parseInt MDN recommends using the unary operator + instead, as in
+"12.12"
=> 12.12
MDN Link
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.
you know that parseFloat() is based on the browser. So as far as I know the browser could crash after 200 values, could work just fine after 10.000 value.
It depends on how many tabs that browser has, what other scripts is running, how much CPU is free for processing, and of course what browser
if your client uses firefox with 1000 addons it will never run your script smoothly.
just my opinion. If you want to do it nice you should preprocess on a server then display.
Type
javascript:a = +new Date; x = 100000; while (--x) parseFloat("21.23"); alert(+new Date - a);
Into your url bar.
This is the only way to know for sure.
In honesty, you can't answer the question. It depends on the browser, for example, firefox 8 should be faster than 6, and so on.

Large substrings ~9000x faster in Firefox than Chrome: why?

The Benchmark: http://jsperf.com/substringing
So, I'm starting up my very first HTML5 browser-based client-side project. It's going to have to parse very, very large text files into, essentially, an array or arrays of objects. I know how I'm going to go about coding it; my primary concern right now is getting the parser code as fast as I can get it, and my primary testbed is Chrome. However, while looking at the differences between substring methods (I haven't touched JavaScript in a long, long time), I noticed that this benchmark was incredibly slow in Chrome compared to FireFox. Why?
My first assumption is that it has to do with the way FireFox's JS engine would handle string objects, and that for FireFox this operation is simple pointer manipulation, while for Chrome it's actually doing hard copies. But, I'm not sure why Chrome wouldn't do pointer manipulation or why FireFox would. Anyone have some insight?
JSPerf appears to be throwing out my FireFox results, not displaying them on the BrowserScope. For me, I'm getting 9,568,203 ±1.44% Ops/sec on .substr() in FF4.
Edit: So I see a FF3.5 performance result down there actually below Chrome. So I decided to test my pointers hypothesis. This brought me to a 2nd revision of my Substrings test, which is doing 1,092,718±1.62% Ops/sec in FF4 versus 1,195±3.81% Ops/sec in Chrome, down to only 1000x faster, but still an inexplicable difference in performance.
A postscriptum: No, I'm not concerned one lick about Internet Explorer. I'm concerned about trying to improve my skills and getting to know this language on a deeper level.
In the case of Spidermonkey (the JS engine in Firefox), a substring() call just creates a new "dependent string": a string object that stores a pointer to the thing it's a substring off and the start and end offsets. This is precisely to make substring() fast, and is an obvious optimization given immutable strings.
As for why V8 does not do that... A possibility is that V8 is trying to save space: in the dependent string setup if you hold on to the substring but forget the original string, the original string can't get GCed because the substring is using part of its string data.
In any case, I just looked at the V8 source, ans it looks like they just don't do any sort of dependent strings at all; the comments don't explain why they don't, though.
[Update, 12/2013]: A few months after I gave the above answer V8 added support for dependent strings, as Paul Draper points out.
Have you eliminated the reading of .length from your benchmark results?
I believe V8 has a few representations of a string:
1. a sequence of ASCII bytes
2. a sequence of UTF-16 code units.
3. a slice of a string (result of substring)
4. a concatenation of two strings.
Number 4 is what makes string += efficient.
I'm just guessing but if they're trying to pack two string pointers and a length into a small space, they may not be able to cache large lengths with the pointers, so may end up walking the joined link list in order to compute the length. This assumes of course that Array.prototype.join creates strings of form (4) from the array parts.
It does lead to a testable hypothesis which would explain the discrepancy even absent buffer copies.
EDIT:
I looked through the V8 source code and StringBuilderConcat is where I would start pulling, especially runtime.cc.

Greasemonkey Storage

Is there any limit on how much data can be stored using GM_setValue?
GM stores it in properties. Open about:config and look for them.
According to http://diveintogreasemonkey.org/api/gm_getvalue.html, you can find them in the greasemonkey.scriptvals branch.
This sqlite info on its limits shows some default limits for strings and blobs, but they may be changed by Firefox.
More information is in the Greasespot Wiki:
The Firefox preference store is not designed for storing large amounts of data. There are no hard limits, but very large amounts of data may cause Firefox to consume more memory and/or run more slowly.2
The link refers to a discussion in the Greasemonkey Mailinglist. Anthony Lieuallen answers the same question as you posted:
I've just tested this. Running up to a 32 meg string seems to work
without major issues, but 64 or 128 starts to thrash the disk for
virtual memory a fair deal.
According to the site you provided, "The value argument can be a string, boolean, or integer."
Obviously, a string can hold far more information than an integer or boolean.
Since GreaseMonkey scripts are JavaScript, the max length for a GM_setValue is the max length of a JavaScript string. Actually, the JavaScript engine (browser specific) determines the max length of a string.
I do not know any specifics, but you could write a script to determine max length.
Keep doubling length until you get an error. Then, try a value halfway between maxGoodLen and minBadLen until maxGoodLen = maxBadLen - 1.

Categories