-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1612 from Pauan/cache
Initial interning implementation
- Loading branch information
Showing
12 changed files
with
248 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use cfg_if::cfg_if; | ||
|
||
|
||
cfg_if! { | ||
if #[cfg(feature = "enable-interning")] { | ||
use std::thread_local; | ||
use std::string::String; | ||
use std::borrow::ToOwned; | ||
use std::cell::RefCell; | ||
use std::collections::HashMap; | ||
use crate::JsValue; | ||
|
||
struct Cache { | ||
entries: RefCell<HashMap<String, JsValue>>, | ||
} | ||
|
||
thread_local! { | ||
static CACHE: Cache = Cache { | ||
entries: RefCell::new(HashMap::new()), | ||
}; | ||
} | ||
|
||
/// This returns the raw index of the cached JsValue, so you must take care | ||
/// so that you don't use it after it is freed. | ||
pub(crate) fn unsafe_get_str(s: &str) -> Option<u32> { | ||
CACHE.with(|cache| { | ||
let cache = cache.entries.borrow(); | ||
|
||
cache.get(s).map(|x| x.idx) | ||
}) | ||
} | ||
|
||
fn intern_str(key: &str) { | ||
CACHE.with(|cache| { | ||
let mut cache = cache.entries.borrow_mut(); | ||
|
||
// Can't use `entry` because `entry` requires a `String` | ||
if !cache.contains_key(key) { | ||
cache.insert(key.to_owned(), JsValue::from(key)); | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
|
||
|
||
/// Interns Rust strings so that it's much faster to send them to JS. | ||
/// | ||
/// Sending strings from Rust to JS is slow, because it has to do a full `O(n)` | ||
/// copy and *also* encode from UTF-8 to UTF-16. This must be done every single | ||
/// time a string is sent to JS. | ||
/// | ||
/// If you are sending the same string multiple times, you can call this `intern` | ||
/// function, which simply returns its argument unchanged: | ||
/// | ||
/// ```rust | ||
/// # use wasm_bindgen::intern; | ||
/// intern("foo") // returns "foo" | ||
/// # ; | ||
/// ``` | ||
/// | ||
/// However, if you enable the `"enable-interning"` feature for wasm-bindgen, | ||
/// then it will add the string into an internal cache. | ||
/// | ||
/// When you send that cached string to JS, it will look it up in the cache, | ||
/// which completely avoids the `O(n)` copy and encoding. This has a significant | ||
/// speed boost (as high as 783%)! | ||
/// | ||
/// However, there is a small cost to this caching, so you shouldn't cache every | ||
/// string. Only cache strings which have a high likelihood of being sent | ||
/// to JS multiple times. | ||
/// | ||
/// Also, keep in mind that this function is a *performance hint*: it's not | ||
/// *guaranteed* that the string will be cached, and the caching strategy | ||
/// might change at any time, so don't rely upon it. | ||
#[inline] | ||
pub fn intern(s: &str) -> &str { | ||
#[cfg(feature = "enable-interning")] | ||
intern_str(s); | ||
|
||
s | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod intern; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.