| 1 | /*
|
|---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
|---|
| 3 | Author Mark Knichel @mknichel
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | "use strict";
|
|---|
| 7 |
|
|---|
| 8 | let dualStringBufferCaching = true;
|
|---|
| 9 |
|
|---|
| 10 | /**
|
|---|
| 11 | * @returns {boolean} Whether the optimization to cache copies of both the
|
|---|
| 12 | * string and buffer version of source content is enabled. This is enabled by
|
|---|
| 13 | * default to improve performance but can consume more memory since values are
|
|---|
| 14 | * stored twice.
|
|---|
| 15 | */
|
|---|
| 16 | function isDualStringBufferCachingEnabled() {
|
|---|
| 17 | return dualStringBufferCaching;
|
|---|
| 18 | }
|
|---|
| 19 |
|
|---|
| 20 | /**
|
|---|
| 21 | * Enables an optimization to save both string and buffer in memory to avoid
|
|---|
| 22 | * repeat conversions between the two formats when they are requested. This
|
|---|
| 23 | * is enabled by default. This option can improve performance but can consume
|
|---|
| 24 | * additional memory since values are stored twice.
|
|---|
| 25 | * @returns {void}
|
|---|
| 26 | */
|
|---|
| 27 | function enableDualStringBufferCaching() {
|
|---|
| 28 | dualStringBufferCaching = true;
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | /**
|
|---|
| 32 | * Disables the optimization to save both string and buffer in memory. This
|
|---|
| 33 | * may increase performance but should reduce memory usage in the Webpack
|
|---|
| 34 | * compiler.
|
|---|
| 35 | * @returns {void}
|
|---|
| 36 | */
|
|---|
| 37 | function disableDualStringBufferCaching() {
|
|---|
| 38 | dualStringBufferCaching = false;
|
|---|
| 39 | }
|
|---|
| 40 |
|
|---|
| 41 | const interningStringMap = new Map();
|
|---|
| 42 |
|
|---|
| 43 | let enableStringInterningRefCount = 0;
|
|---|
| 44 |
|
|---|
| 45 | /**
|
|---|
| 46 | * @returns {boolean} value
|
|---|
| 47 | */
|
|---|
| 48 | function isStringInterningEnabled() {
|
|---|
| 49 | return enableStringInterningRefCount > 0;
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | /**
|
|---|
| 53 | * Starts a memory optimization to avoid repeat copies of the same string in
|
|---|
| 54 | * memory by caching a single reference to the string. This can reduce memory
|
|---|
| 55 | * usage if the same string is repeated many times in the compiler, such as
|
|---|
| 56 | * when Webpack layers are used with the same files.
|
|---|
| 57 | *
|
|---|
| 58 | * {@link exitStringInterningRange} should be called when string interning is
|
|---|
| 59 | * no longer necessary to free up the memory used by the interned strings. If
|
|---|
| 60 | * {@link enterStringInterningRange} has been called multiple times, then
|
|---|
| 61 | * this method may not immediately free all the memory until
|
|---|
| 62 | * {@link exitStringInterningRange} has been called to end all string
|
|---|
| 63 | * interning ranges.
|
|---|
| 64 | * @returns {void}
|
|---|
| 65 | */
|
|---|
| 66 | function enterStringInterningRange() {
|
|---|
| 67 | enableStringInterningRefCount++;
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | /**
|
|---|
| 71 | * Stops the current string interning range. Once all string interning ranges
|
|---|
| 72 | * have been exited, this method will free all the memory used by the interned
|
|---|
| 73 | * strings. This method should be called once for each time that
|
|---|
| 74 | * {@link enterStringInterningRange} was called.
|
|---|
| 75 | * @returns {void}
|
|---|
| 76 | */
|
|---|
| 77 | function exitStringInterningRange() {
|
|---|
| 78 | if (--enableStringInterningRefCount <= 0) {
|
|---|
| 79 | interningStringMap.clear();
|
|---|
| 80 | enableStringInterningRefCount = 0;
|
|---|
| 81 | }
|
|---|
| 82 | }
|
|---|
| 83 |
|
|---|
| 84 | /**
|
|---|
| 85 | * Saves the string in a map to ensure that only one copy of the string exists
|
|---|
| 86 | * in memory at a given time. This is controlled by {@link enableStringInterning}
|
|---|
| 87 | * and {@link disableStringInterning}. Callers are expect to manage the memory
|
|---|
| 88 | * of the interned strings by calling {@link disableStringInterning} after the
|
|---|
| 89 | * compiler no longer needs to save the interned memory.
|
|---|
| 90 | * @param {string} str A string to be interned.
|
|---|
| 91 | * @returns {string} The original string or a reference to an existing string of the same value if it has already been interned.
|
|---|
| 92 | */
|
|---|
| 93 | function internString(str) {
|
|---|
| 94 | if (
|
|---|
| 95 | !isStringInterningEnabled() ||
|
|---|
| 96 | !str ||
|
|---|
| 97 | str.length < 128 ||
|
|---|
| 98 | typeof str !== "string"
|
|---|
| 99 | ) {
|
|---|
| 100 | return str;
|
|---|
| 101 | }
|
|---|
| 102 | let internedString = interningStringMap.get(str);
|
|---|
| 103 | if (internedString === undefined) {
|
|---|
| 104 | internedString = str;
|
|---|
| 105 | interningStringMap.set(str, internedString);
|
|---|
| 106 | }
|
|---|
| 107 | return internedString;
|
|---|
| 108 | }
|
|---|
| 109 |
|
|---|
| 110 | module.exports = {
|
|---|
| 111 | disableDualStringBufferCaching,
|
|---|
| 112 | enableDualStringBufferCaching,
|
|---|
| 113 | enterStringInterningRange,
|
|---|
| 114 | exitStringInterningRange,
|
|---|
| 115 | internString,
|
|---|
| 116 | isDualStringBufferCachingEnabled,
|
|---|
| 117 | };
|
|---|