prometheus-client-mmap 0.20.0 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaa63589f21ccefd35765317ce8e1b4ca2a11dc41d3391554fb7a5182616db66
4
- data.tar.gz: d58b2c4813b211ced7bf7d3f6c2277a9d5195af3d7ee19ef15ce892f70f4bc4a
3
+ metadata.gz: f91fbb3a1899d0093d51d92ab8dceec80981c6160b3a09d35d90117f29e6c3d0
4
+ data.tar.gz: fea591800d5a3a2344082fd38df75f35aea8b5bf5394bcd7e20bf80d14dd48fd
5
5
  SHA512:
6
- metadata.gz: 24ec66d0f72463e93881eede6333e714f222e48812cf172efd023d17359380513c368ede182476071b02f55ab138aea44b00a0f05c7334c012bcb9083d00e356
7
- data.tar.gz: e674a37306171bad42464096958a4d32dd4c8d36f677b8197eb8b64aaf5944c6ec372d6b0a461de10c59204624520be472f78253438c1558b377d99c447074d7
6
+ metadata.gz: f6e98dda485f79a83fe614a21c52444fad33a69b208c4a6d637516c0390f79c9c54216dda50f7b151483d3e69fe4e7739ed0076984cb7497c59110f0f941b664
7
+ data.tar.gz: 30bc5288dd7247222128b99a4cf88bdde9ca8625682b0d013dc5ea9cd6ce12aa5285be4b3a875f9a933dcc23e943c4b2cccc9ad9c53e273754a4dac46ddee1ed
@@ -9,7 +9,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
9
9
  checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
10
10
  dependencies = [
11
11
  "cfg-if",
12
- "getrandom",
13
12
  "once_cell",
14
13
  "version_check",
15
14
  ]
@@ -161,8 +160,8 @@ dependencies = [
161
160
  name = "fast_mmaped_file_rs"
162
161
  version = "0.1.0"
163
162
  dependencies = [
164
- "ahash",
165
163
  "bstr",
164
+ "hashbrown",
166
165
  "indoc",
167
166
  "libc",
168
167
  "magnus",
@@ -212,6 +211,15 @@ version = "0.3.1"
212
211
  source = "registry+https://github.com/rust-lang/crates.io-index"
213
212
  checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
214
213
 
214
+ [[package]]
215
+ name = "hashbrown"
216
+ version = "0.13.2"
217
+ source = "registry+https://github.com/rust-lang/crates.io-index"
218
+ checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
219
+ dependencies = [
220
+ "ahash",
221
+ ]
222
+
215
223
  [[package]]
216
224
  name = "hermit-abi"
217
225
  version = "0.3.1"
@@ -6,7 +6,7 @@ edition = "2021"
6
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
7
 
8
8
  [dependencies]
9
- ahash = "0.8"
9
+ hashbrown = "0.13"
10
10
  libc = "0.2"
11
11
  magnus = { git = "https://github.com/matsadler/magnus", branch = "main", features = ["rb-sys"] }
12
12
  memmap2 = "0.5"
@@ -1,7 +1,9 @@
1
1
  require "mkmf"
2
2
  require "rb_sys/mkmf"
3
3
 
4
- create_rust_makefile("prometheus-client-mmap/fast_mmaped_file_rs") do |r|
4
+ create_rust_makefile("fast_mmaped_file_rs") do |r|
5
+ r.auto_install_rust_toolchain = false
6
+
5
7
  if enable_config('fail-on-warning')
6
8
  r.extra_rustflags = ["-Dwarnings"]
7
9
  end
@@ -1,4 +1,6 @@
1
1
  use magnus::{StaticSymbol, Symbol};
2
+ use std::fmt::Write;
3
+ use std::str;
2
4
 
3
5
  use crate::error::{MmapError, RubyError};
4
6
  use crate::file_info::FileInfo;
@@ -22,27 +24,55 @@ pub struct EntryData {
22
24
  pub pid: Option<String>,
23
25
  }
24
26
 
25
- impl EntryData {
26
- pub fn new(raw_entry: &RawEntry, file_info: &FileInfo, pid_significant: bool) -> Result<Self> {
27
- let mut buf = Vec::new();
27
+ impl<'a> PartialEq<BorrowedData<'a>> for EntryData {
28
+ fn eq(&self, other: &BorrowedData) -> bool {
29
+ self.pid.as_deref() == other.pid && self.json == other.json
30
+ }
31
+ }
32
+
33
+ impl<'a> TryFrom<BorrowedData<'a>> for EntryData {
34
+ type Error = MmapError;
28
35
 
29
- if buf.try_reserve_exact(raw_entry.encoded_len()).is_err() {
30
- return Err(MmapError::OutOfMemory(raw_entry.encoded_len()));
36
+ fn try_from(borrowed: BorrowedData) -> Result<Self> {
37
+ let mut json = String::new();
38
+ if json.try_reserve_exact(borrowed.json.len()).is_err() {
39
+ return Err(MmapError::OutOfMemory(borrowed.json.len()));
31
40
  }
41
+ json.push_str(borrowed.json);
32
42
 
33
- buf.resize(raw_entry.encoded_len(), 0);
34
- buf.copy_from_slice(raw_entry.json());
43
+ Ok(Self {
44
+ json,
45
+ // Don't bother checking for allocation failure, typically ~10 bytes
46
+ pid: borrowed.pid.map(|p| p.to_string()),
47
+ })
48
+ }
49
+ }
50
+
51
+ /// A borrowed copy of the JSON string and pid for a `FileEntry`. We use this
52
+ /// to check if a given string/pid combination is present in the `EntryMap`,
53
+ /// copying them to owned values only when needed.
54
+ #[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
55
+ pub struct BorrowedData<'a> {
56
+ pub json: &'a str,
57
+ pub pid: Option<&'a str>,
58
+ }
35
59
 
36
- let json = String::from_utf8(buf)
60
+ impl<'a> BorrowedData<'a> {
61
+ pub fn new(
62
+ raw_entry: &'a RawEntry,
63
+ file_info: &'a FileInfo,
64
+ pid_significant: bool,
65
+ ) -> Result<Self> {
66
+ let json = str::from_utf8(raw_entry.json())
37
67
  .map_err(|e| MmapError::Encoding(format!("invalid UTF-8 in entry JSON: {e}")))?;
38
68
 
39
69
  let pid = if pid_significant {
40
- Some(file_info.pid.clone())
70
+ Some(file_info.pid.as_str())
41
71
  } else {
42
72
  None
43
73
  };
44
74
 
45
- Ok(EntryData { json, pid })
75
+ Ok(Self { json, pid })
46
76
  }
47
77
  }
48
78
 
@@ -121,7 +151,8 @@ impl FileEntry {
121
151
 
122
152
  entry.append_entry(metrics_data, &mut out)?;
123
153
 
124
- out.push_str(&format!(" {}\n", entry.meta.value));
154
+ writeln!(&mut out, " {}", entry.meta.value)
155
+ .map_err(|e| MmapError::Other(format!("Failed to append to output: {e}")))?;
125
156
 
126
157
  processed_count += 1;
127
158
  }
@@ -419,7 +450,9 @@ mod test {
419
450
  .zip(file_infos)
420
451
  .map(|(entry, info)| {
421
452
  let meta = EntryMetadata::new(&entry, &info).unwrap();
422
- let data = EntryData::new(&entry, &info, meta.is_pid_significant()).unwrap();
453
+ let borrowed =
454
+ BorrowedData::new(&entry, &info, meta.is_pid_significant()).unwrap();
455
+ let data = EntryData::try_from(borrowed).unwrap();
423
456
  FileEntry { data, meta }
424
457
  })
425
458
  .collect();
@@ -526,7 +559,9 @@ mod test {
526
559
  .map(|s| RawEntry::from_slice(s).unwrap())
527
560
  .map(|entry| {
528
561
  let meta = EntryMetadata::new(&entry, &info).unwrap();
529
- let data = EntryData::new(&entry, &info, meta.is_pid_significant()).unwrap();
562
+ let borrowed =
563
+ BorrowedData::new(&entry, &info, meta.is_pid_significant()).unwrap();
564
+ let data = EntryData::try_from(borrowed).unwrap();
530
565
  FileEntry { data, meta }
531
566
  })
532
567
  .collect();
@@ -1,9 +1,11 @@
1
- use ahash::AHashMap;
1
+ use hashbrown::hash_map::RawEntryMut;
2
+ use hashbrown::HashMap;
2
3
  use magnus::{exception::*, Error, RArray};
4
+ use std::hash::{BuildHasher, Hash, Hasher};
3
5
  use std::mem::size_of;
4
6
 
5
7
  use crate::error::MmapError;
6
- use crate::file_entry::{EntryData, EntryMetadata, FileEntry};
8
+ use crate::file_entry::{BorrowedData, EntryData, EntryMetadata, FileEntry};
7
9
  use crate::file_info::FileInfo;
8
10
  use crate::raw_entry::RawEntry;
9
11
  use crate::util::read_u32;
@@ -17,12 +19,12 @@ use crate::{err, HEADER_SIZE};
17
19
  /// allows us to have multiple entries on the map for multiple pids using the
18
20
  /// same string.
19
21
  #[derive(Default, Debug)]
20
- pub struct EntryMap(AHashMap<EntryData, EntryMetadata>);
22
+ pub struct EntryMap(HashMap<EntryData, EntryMetadata>);
21
23
 
22
24
  impl EntryMap {
23
25
  /// Construct a new EntryMap.
24
26
  pub fn new() -> Self {
25
- Self(AHashMap::new())
27
+ Self(HashMap::new())
26
28
  }
27
29
 
28
30
  /// Given a list of files, read each one into memory and parse the metrics it contains.
@@ -95,12 +97,28 @@ impl EntryMap {
95
97
  /// Check if the `EntryMap` already contains the JSON string.
96
98
  /// If yes, update the associated value, if not insert the
97
99
  /// entry into the map.
98
- pub fn merge_or_store(&mut self, data: EntryData, meta: EntryMetadata) {
99
- if let Some(existing) = self.0.get_mut(&data) {
100
- existing.merge(&meta);
101
- } else {
102
- self.0.insert(data, meta);
100
+ pub fn merge_or_store(&mut self, data: BorrowedData, meta: EntryMetadata) -> Result<()> {
101
+ // Manually hash the `BorrowedData` and perform an equality check on the
102
+ // key. This allows us to perform the comparison without allocating a
103
+ // new `EntryData` that may not be needed.
104
+ let mut state = self.0.hasher().build_hasher();
105
+ data.hash(&mut state);
106
+ let hash = state.finish();
107
+
108
+ match self.0.raw_entry_mut().from_hash(hash, |k| k == &data) {
109
+ RawEntryMut::Vacant(entry) => {
110
+ // Allocate a new `EntryData` as the JSON/pid combination is
111
+ // not present in the map.
112
+ let owned = EntryData::try_from(data)?;
113
+ entry.insert(owned, meta);
114
+ }
115
+ RawEntryMut::Occupied(mut entry) => {
116
+ let existing = entry.get_mut();
117
+ existing.merge(&meta);
118
+ }
103
119
  }
120
+
121
+ Ok(())
104
122
  }
105
123
 
106
124
  /// Parse metrics data from a `.db` file and store in the `EntryMap`.
@@ -135,9 +153,9 @@ impl EntryMap {
135
153
  }
136
154
 
137
155
  let meta = EntryMetadata::new(&raw_entry, &file_info)?;
138
- let data = EntryData::new(&raw_entry, &file_info, meta.is_pid_significant())?;
156
+ let data = BorrowedData::new(&raw_entry, &file_info, meta.is_pid_significant())?;
139
157
 
140
- self.merge_or_store(data, meta);
158
+ self.merge_or_store(data, meta)?;
141
159
 
142
160
  pos += raw_entry.total_len();
143
161
  }
@@ -155,6 +173,16 @@ mod test {
155
173
  use crate::file_entry::FileEntry;
156
174
  use crate::testhelper::{self, TestFile};
157
175
 
176
+ impl EntryData {
177
+ /// A helper function for tests to convert owned data to references.
178
+ fn as_borrowed(&self) -> BorrowedData {
179
+ BorrowedData {
180
+ json: &self.json,
181
+ pid: self.pid.as_deref(),
182
+ }
183
+ }
184
+ }
185
+
158
186
  #[test]
159
187
  fn test_into_sorted() {
160
188
  let _cleanup = unsafe { magnus::embed::init() };
@@ -311,7 +339,9 @@ mod test {
311
339
  map.0
312
340
  .insert(starting_entry.data.clone(), starting_entry.meta.clone());
313
341
 
314
- map.merge_or_store(matching_entry.data, matching_entry.meta);
342
+ let matching_borrowed = matching_entry.data.as_borrowed();
343
+ map.merge_or_store(matching_borrowed, matching_entry.meta)
344
+ .unwrap();
315
345
 
316
346
  assert_eq!(
317
347
  5.0,
@@ -320,10 +350,12 @@ mod test {
320
350
  );
321
351
  assert_eq!(1, map.0.len(), "no entry added");
322
352
 
353
+ let same_key_different_worker_borrowed = same_key_different_worker.data.as_borrowed();
323
354
  map.merge_or_store(
324
- same_key_different_worker.data,
355
+ same_key_different_worker_borrowed,
325
356
  same_key_different_worker.meta,
326
- );
357
+ )
358
+ .unwrap();
327
359
 
328
360
  assert_eq!(
329
361
  5.0,
@@ -333,7 +365,9 @@ mod test {
333
365
 
334
366
  assert_eq!(2, map.0.len(), "additional entry added");
335
367
 
336
- map.merge_or_store(unmatched_entry.data, unmatched_entry.meta);
368
+ let unmatched_entry_borrowed = unmatched_entry.data.as_borrowed();
369
+ map.merge_or_store(unmatched_entry_borrowed, unmatched_entry.meta)
370
+ .unwrap();
337
371
 
338
372
  assert_eq!(
339
373
  5.0,
@@ -1,5 +1,5 @@
1
1
  module Prometheus
2
2
  module Client
3
- VERSION = '0.20.0'.freeze
3
+ VERSION = '0.20.2'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prometheus-client-mmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.0
4
+ version: 0.20.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Schmidt
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-04-13 00:00:00.000000000 Z
12
+ date: 2023-04-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rb_sys
@@ -130,7 +130,6 @@ files:
130
130
  - ext/fast_mmaped_file/value_access.c
131
131
  - ext/fast_mmaped_file/value_access.h
132
132
  - ext/fast_mmaped_file_rs/.cargo/config.toml
133
- - ext/fast_mmaped_file_rs/.tool-versions
134
133
  - ext/fast_mmaped_file_rs/Cargo.lock
135
134
  - ext/fast_mmaped_file_rs/Cargo.toml
136
135
  - ext/fast_mmaped_file_rs/README.md
@@ -213,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
212
  - !ruby/object:Gem::Version
214
213
  version: '0'
215
214
  requirements: []
216
- rubygems_version: 3.4.10
215
+ rubygems_version: 3.4.12
217
216
  signing_key:
218
217
  specification_version: 4
219
218
  summary: A suite of instrumentation metric primitivesthat can be exposed through a
@@ -1 +0,0 @@
1
- rust 1.65.0