omnizip 0.3.52 → 0.3.53
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 +4 -4
- data/CHANGELOG.md +29 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +1 -1
- data/lib/omnizip/buffer/memory_extractor.rb +3 -16
- data/lib/omnizip/buffer/seven_zip_bridge.rb +13 -0
- data/lib/omnizip/buffer.rb +23 -21
- data/lib/omnizip/checksums/verifier.rb +2 -2
- data/lib/omnizip/chunked.rb +14 -21
- data/lib/omnizip/formats/cpio/reader.rb +1 -1
- data/lib/omnizip/formats/iso/reader.rb +3 -3
- data/lib/omnizip/formats/iso/volume_descriptor.rb +2 -2
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +0 -20
- data/lib/omnizip/formats/rar/decompressor.rb +7 -7
- data/lib/omnizip/formats/rar/reader.rb +2 -2
- data/lib/omnizip/formats/rpm.rb +4 -4
- data/lib/omnizip/formats/seven_zip/reader.rb +1 -1
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +1 -1
- data/lib/omnizip/formats/xar/reader.rb +2 -2
- data/lib/omnizip/formats/zip/reader.rb +96 -8
- data/lib/omnizip/models/conversion_result.rb +75 -63
- data/lib/omnizip/models/filter_config.rb +34 -44
- data/lib/omnizip/models/match_result.rb +35 -18
- data/lib/omnizip/models/optimization_suggestion.rb +45 -41
- data/lib/omnizip/models/performance_result.rb +53 -47
- data/lib/omnizip/models/profile_report.rb +70 -36
- data/lib/omnizip/parallel/parallel_extractor.rb +2 -2
- data/lib/omnizip/parallel/worker_pool.rb +3 -3
- data/lib/omnizip/profiler/report_generator.rb +1 -1
- data/lib/omnizip/version.rb +1 -1
- data/lib/omnizip/zip/file.rb +1 -1
- metadata +1 -1
|
@@ -1,84 +1,111 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
3
5
|
module Omnizip
|
|
4
6
|
module Models
|
|
5
|
-
# Model for format conversion results
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
7
|
+
# Model for format conversion results.
|
|
8
|
+
#
|
|
9
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
10
|
+
# The percentage/speed keys serialize the derived methods; the
|
|
11
|
+
# attribute names differ from the keys so the framework's
|
|
12
|
+
# generated readers do not shadow the methods.
|
|
13
|
+
class ConversionResult < Lutaml::Model::Serializable
|
|
14
|
+
attribute :source_path, :string
|
|
15
|
+
attribute :target_path, :string
|
|
16
|
+
attribute :source_format, :symbol
|
|
17
|
+
attribute :target_format, :symbol
|
|
18
|
+
attribute :source_size, :integer
|
|
19
|
+
attribute :target_size, :integer
|
|
20
|
+
attribute :duration, :double
|
|
21
|
+
attribute :entry_count, :integer
|
|
22
|
+
attribute :warnings, :string, collection: true, default: []
|
|
23
|
+
|
|
24
|
+
attribute :ratio, :double, method: :compression_ratio_value
|
|
25
|
+
attribute :reduction_pct, :double, method: :size_reduction
|
|
26
|
+
attribute :ratio_pct, :double, method: :size_ratio
|
|
27
|
+
attribute :speed, :double, method: :processing_speed
|
|
28
|
+
|
|
29
|
+
key_value do
|
|
30
|
+
map "source_path", to: :source_path,
|
|
31
|
+
render_default: true, render_nil: true
|
|
32
|
+
map "target_path", to: :target_path,
|
|
33
|
+
render_default: true, render_nil: true
|
|
34
|
+
map "source_format", to: :source_format,
|
|
35
|
+
render_default: true, render_nil: true
|
|
36
|
+
map "target_format", to: :target_format,
|
|
37
|
+
render_default: true, render_nil: true
|
|
38
|
+
map "source_size", to: :source_size,
|
|
39
|
+
render_default: true, render_nil: true
|
|
40
|
+
map "target_size", to: :target_size,
|
|
41
|
+
render_default: true, render_nil: true
|
|
42
|
+
map "size_reduction", to: :reduction_pct,
|
|
43
|
+
render_default: true, render_nil: true
|
|
44
|
+
map "size_ratio", to: :ratio_pct,
|
|
45
|
+
render_default: true, render_nil: true
|
|
46
|
+
map "duration", to: :duration,
|
|
47
|
+
render_default: true, render_nil: true
|
|
48
|
+
map "entry_count", to: :entry_count,
|
|
49
|
+
render_default: true, render_nil: true
|
|
50
|
+
map "processing_speed", to: :speed,
|
|
51
|
+
render_default: true, render_nil: true
|
|
52
|
+
map "warnings", to: :warnings,
|
|
53
|
+
render_default: true, render_nil: true
|
|
54
|
+
map "compression_ratio", to: :ratio,
|
|
55
|
+
render_default: true, render_nil: true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# lutaml-model 0.8.x does not render empty-string/empty-collection
|
|
59
|
+
# defaults, so they are assigned explicitly to keep every key
|
|
60
|
+
# present in the serialized shape.
|
|
61
|
+
def initialize(attrs = {})
|
|
62
|
+
super({ warnings: [] }.merge(attrs))
|
|
42
63
|
end
|
|
43
64
|
|
|
44
65
|
# Get size reduction percentage
|
|
66
|
+
#
|
|
45
67
|
# @return [Float] Size reduction as percentage
|
|
46
68
|
def size_reduction
|
|
47
|
-
return 0.0 if source_size.zero?
|
|
69
|
+
return 0.0 if source_size.to_i.zero?
|
|
48
70
|
|
|
49
71
|
((source_size - target_size).to_f / source_size * 100).round(2)
|
|
50
72
|
end
|
|
51
73
|
|
|
52
74
|
# Get size ratio
|
|
75
|
+
#
|
|
53
76
|
# @return [Float] Target size as percentage of source size
|
|
54
77
|
def size_ratio
|
|
55
|
-
return 0.0 if source_size.zero?
|
|
78
|
+
return 0.0 if source_size.to_i.zero?
|
|
56
79
|
|
|
57
80
|
(target_size.to_f / source_size * 100).round(2)
|
|
58
81
|
end
|
|
59
82
|
|
|
60
83
|
# Check if conversion resulted in smaller file
|
|
84
|
+
#
|
|
61
85
|
# @return [Boolean] True if target is smaller
|
|
62
86
|
def smaller?
|
|
63
87
|
target_size < source_size
|
|
64
88
|
end
|
|
65
89
|
|
|
66
90
|
# Check if conversion resulted in larger file
|
|
91
|
+
#
|
|
67
92
|
# @return [Boolean] True if target is larger
|
|
68
93
|
def larger?
|
|
69
94
|
target_size > source_size
|
|
70
95
|
end
|
|
71
96
|
|
|
72
97
|
# Check if there were warnings
|
|
98
|
+
#
|
|
73
99
|
# @return [Boolean] True if warnings exist
|
|
74
100
|
def warnings?
|
|
75
101
|
!warnings.empty?
|
|
76
102
|
end
|
|
77
103
|
|
|
78
104
|
# Get average processing speed
|
|
105
|
+
#
|
|
79
106
|
# @return [Float] MB/s processing speed
|
|
80
107
|
def processing_speed
|
|
81
|
-
return 0.0 if duration.zero? || source_size.zero?
|
|
108
|
+
return 0.0 if duration.to_f.zero? || source_size.to_i.zero?
|
|
82
109
|
|
|
83
110
|
speed = source_size / duration / 1_048_576.0
|
|
84
111
|
rounded = speed.round(2)
|
|
@@ -86,26 +113,17 @@ module Omnizip
|
|
|
86
113
|
rounded.zero? && speed.positive? ? speed : rounded
|
|
87
114
|
end
|
|
88
115
|
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
target_format: target_format,
|
|
97
|
-
source_size: source_size,
|
|
98
|
-
target_size: target_size,
|
|
99
|
-
size_reduction: size_reduction,
|
|
100
|
-
size_ratio: size_ratio,
|
|
101
|
-
duration: duration,
|
|
102
|
-
entry_count: entry_count,
|
|
103
|
-
processing_speed: processing_speed,
|
|
104
|
-
warnings: warnings,
|
|
105
|
-
}
|
|
116
|
+
# Compression ratio (0.0-1.0 fraction saved by compression)
|
|
117
|
+
#
|
|
118
|
+
# @return [Float]
|
|
119
|
+
def compression_ratio_value
|
|
120
|
+
return 0.0 if source_size.to_i.zero?
|
|
121
|
+
|
|
122
|
+
(1.0 - (target_size.to_f / source_size)).round(4)
|
|
106
123
|
end
|
|
107
124
|
|
|
108
125
|
# Format as human-readable string
|
|
126
|
+
#
|
|
109
127
|
# @return [String] Formatted result
|
|
110
128
|
def to_s
|
|
111
129
|
"Converted #{source_path} (#{format_size(source_size)}) to " \
|
|
@@ -115,12 +133,6 @@ module Omnizip
|
|
|
115
133
|
|
|
116
134
|
private
|
|
117
135
|
|
|
118
|
-
def calculate_compression_ratio
|
|
119
|
-
return 0.0 if source_size.zero?
|
|
120
|
-
|
|
121
|
-
(1.0 - (target_size.to_f / source_size)).round(4)
|
|
122
|
-
end
|
|
123
|
-
|
|
124
136
|
def format_size(bytes)
|
|
125
137
|
Omnizip::CliOutputFormatter.format_size(bytes)
|
|
126
138
|
end
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
# See the COPYING file for the complete text of the license.
|
|
17
17
|
#
|
|
18
18
|
|
|
19
|
+
require "lutaml/model"
|
|
20
|
+
|
|
19
21
|
module Omnizip
|
|
20
22
|
module Models
|
|
21
23
|
# Configuration model for a filter in a compression pipeline.
|
|
@@ -23,6 +25,8 @@ module Omnizip
|
|
|
23
25
|
# This class replaces hash-based filter configuration with a proper
|
|
24
26
|
# model class. It provides format-aware ID resolution and validation.
|
|
25
27
|
#
|
|
28
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
29
|
+
#
|
|
26
30
|
# @example Create a BCJ filter configuration
|
|
27
31
|
# config = FilterConfig.new(name: :bcj_x86, architecture: :x86)
|
|
28
32
|
# config.id_for_format(:xz) # => 0x04
|
|
@@ -31,42 +35,39 @@ module Omnizip
|
|
|
31
35
|
# @example Create a Delta filter configuration
|
|
32
36
|
# config = FilterConfig.new(name: :delta)
|
|
33
37
|
# config.delta? # => true
|
|
34
|
-
class FilterConfig
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
class FilterConfig < Lutaml::Model::Serializable
|
|
39
|
+
attribute :name, :symbol
|
|
40
|
+
attribute :properties, :string, default: ""
|
|
41
|
+
attribute :architecture, :symbol
|
|
42
|
+
|
|
43
|
+
key_value do
|
|
44
|
+
map "name", to: :name, render_default: true, render_nil: true
|
|
45
|
+
map "properties", to: :properties,
|
|
46
|
+
render_default: true, render_nil: true
|
|
47
|
+
map "architecture", to: :architecture,
|
|
48
|
+
render_default: true, render_nil: true
|
|
49
|
+
end
|
|
43
50
|
|
|
44
|
-
# Initialize filter configuration.
|
|
51
|
+
# Initialize filter configuration. The legacy +name_sym+ key is
|
|
52
|
+
# accepted as an alias for +name+.
|
|
45
53
|
#
|
|
46
54
|
# @param attributes [Hash] Initialization attributes
|
|
47
55
|
# @option attributes [Symbol] :name Filter name
|
|
48
|
-
# @option attributes [Symbol] :name_sym Filter name (
|
|
56
|
+
# @option attributes [Symbol] :name_sym Filter name (alias)
|
|
49
57
|
# @option attributes [String] :properties Binary properties data
|
|
50
58
|
# @option attributes [Symbol] :architecture Target architecture
|
|
51
59
|
def initialize(attributes = {})
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
attrs = attributes.dup
|
|
61
|
+
attrs[:name] ||= attrs.delete(:name_sym)
|
|
62
|
+
attrs[:properties] ||= "" # empty-string defaults do not render
|
|
63
|
+
super(attrs)
|
|
55
64
|
end
|
|
56
65
|
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
# @param value [Symbol] Filter name
|
|
60
|
-
# @return [void]
|
|
61
|
-
def name=(value)
|
|
62
|
-
@name_sym = value
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Get filter name as symbol.
|
|
66
|
+
# Get filter name as symbol (legacy alias for #name).
|
|
66
67
|
#
|
|
67
68
|
# @return [Symbol] Filter name
|
|
68
69
|
def name_sym
|
|
69
|
-
|
|
70
|
+
name
|
|
70
71
|
end
|
|
71
72
|
|
|
72
73
|
# Get filter instance from registry.
|
|
@@ -74,11 +75,11 @@ module Omnizip
|
|
|
74
75
|
# @return [Object] Filter instance from FilterRegistry
|
|
75
76
|
# @raise [KeyError] If filter not found in registry
|
|
76
77
|
def filter_instance
|
|
77
|
-
filter = Omnizip::FilterRegistry.get(
|
|
78
|
+
filter = Omnizip::FilterRegistry.get(name)
|
|
78
79
|
|
|
79
80
|
# Handle architecture parameter if needed
|
|
80
|
-
if
|
|
81
|
-
filter.new(architecture:
|
|
81
|
+
if architecture && requires_initialize_kwargs?(filter)
|
|
82
|
+
filter.new(architecture: architecture)
|
|
82
83
|
else
|
|
83
84
|
filter.new
|
|
84
85
|
end
|
|
@@ -100,7 +101,7 @@ module Omnizip
|
|
|
100
101
|
filter.id_for_format(format)
|
|
101
102
|
else
|
|
102
103
|
raise NotImplementedError,
|
|
103
|
-
"Filter #{
|
|
104
|
+
"Filter #{name} doesn't support format-aware IDs. " \
|
|
104
105
|
"Use the newer BCJ filter instead."
|
|
105
106
|
end
|
|
106
107
|
end
|
|
@@ -109,14 +110,14 @@ module Omnizip
|
|
|
109
110
|
#
|
|
110
111
|
# @return [Boolean] True if BCJ filter variant
|
|
111
112
|
def bcj?
|
|
112
|
-
|
|
113
|
+
name.to_s.start_with?("bcj_")
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
# Check if this is a Delta filter.
|
|
116
117
|
#
|
|
117
118
|
# @return [Boolean] True if Delta filter
|
|
118
119
|
def delta?
|
|
119
|
-
|
|
120
|
+
name == :delta
|
|
120
121
|
end
|
|
121
122
|
|
|
122
123
|
# Validate configuration.
|
|
@@ -124,26 +125,15 @@ module Omnizip
|
|
|
124
125
|
# @return [Boolean] True if valid
|
|
125
126
|
# @raise [ArgumentError] If filter name is nil or not registered
|
|
126
127
|
def validate!
|
|
127
|
-
raise ArgumentError, "Filter name is required" if
|
|
128
|
+
raise ArgumentError, "Filter name is required" if name.nil?
|
|
128
129
|
|
|
129
|
-
unless Omnizip::FilterRegistry.registered?(
|
|
130
|
-
raise ArgumentError, "Filter not registered: #{
|
|
130
|
+
unless Omnizip::FilterRegistry.registered?(name)
|
|
131
|
+
raise ArgumentError, "Filter not registered: #{name}"
|
|
131
132
|
end
|
|
132
133
|
|
|
133
134
|
true
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
# Convert to hash representation.
|
|
137
|
-
#
|
|
138
|
-
# @return [Hash] Hash representation with :name, :properties, :architecture
|
|
139
|
-
def to_h
|
|
140
|
-
{
|
|
141
|
-
name: @name_sym,
|
|
142
|
-
properties: @properties,
|
|
143
|
-
architecture: @architecture,
|
|
144
|
-
}
|
|
145
|
-
end
|
|
146
|
-
|
|
147
137
|
private
|
|
148
138
|
|
|
149
139
|
# Check if filter class requires keyword arguments for initialize.
|
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
3
5
|
module Omnizip
|
|
4
6
|
module Models
|
|
5
|
-
# Represents the result of pattern matching against archive entries
|
|
7
|
+
# Represents the result of pattern matching against archive entries.
|
|
6
8
|
#
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
10
|
+
# The serialized "matches" is the match COUNT (not the entry
|
|
11
|
+
# objects, which are arbitrary caller types); the live entry
|
|
12
|
+
# collection stays a plain reader.
|
|
13
|
+
class MatchResult < Lutaml::Model::Serializable
|
|
9
14
|
include Enumerable
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
attribute :total_scanned, :integer, default: 0
|
|
17
|
+
|
|
18
|
+
attribute :pattern_repr, :string, method: :pattern_to_s
|
|
19
|
+
attribute :match_count, :integer, method: :count
|
|
20
|
+
attribute :rate, :double, method: :match_rate
|
|
21
|
+
|
|
22
|
+
key_value do
|
|
23
|
+
map "pattern", to: :pattern_repr,
|
|
24
|
+
render_default: true, render_nil: true
|
|
25
|
+
map "matches", to: :match_count,
|
|
26
|
+
render_default: true, render_nil: true
|
|
27
|
+
map "scanned", to: :total_scanned,
|
|
28
|
+
render_default: true, render_nil: true
|
|
29
|
+
map "match_rate", to: :rate,
|
|
30
|
+
render_default: true, render_nil: true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :matches, :pattern
|
|
12
34
|
|
|
13
35
|
# Initialize a new match result
|
|
14
36
|
#
|
|
15
37
|
# @param pattern [Object] The pattern that was matched
|
|
16
38
|
# @param matches [Array] Array of matched entries
|
|
17
39
|
# @param total_scanned [Integer] Total entries scanned
|
|
18
|
-
def initialize(pattern, matches: [], total_scanned: 0)
|
|
40
|
+
def initialize(pattern = nil, matches: [], total_scanned: 0)
|
|
41
|
+
super(total_scanned: total_scanned)
|
|
19
42
|
@pattern = pattern
|
|
20
43
|
@matches = Array(matches)
|
|
21
|
-
@total_scanned = total_scanned
|
|
22
44
|
end
|
|
23
45
|
|
|
24
46
|
# Add a matched entry
|
|
@@ -35,7 +57,7 @@ module Omnizip
|
|
|
35
57
|
# @param count [Integer] Number to increment by
|
|
36
58
|
# @return [self]
|
|
37
59
|
def increment_scanned(count = 1)
|
|
38
|
-
|
|
60
|
+
self.total_scanned = total_scanned + count
|
|
39
61
|
self
|
|
40
62
|
end
|
|
41
63
|
|
|
@@ -64,9 +86,9 @@ module Omnizip
|
|
|
64
86
|
#
|
|
65
87
|
# @return [Float] Match rate between 0.0 and 1.0
|
|
66
88
|
def match_rate
|
|
67
|
-
return 0.0 if
|
|
89
|
+
return 0.0 if total_scanned.zero?
|
|
68
90
|
|
|
69
|
-
count.to_f /
|
|
91
|
+
count.to_f / total_scanned
|
|
70
92
|
end
|
|
71
93
|
|
|
72
94
|
# Get match percentage
|
|
@@ -108,16 +130,11 @@ module Omnizip
|
|
|
108
130
|
@matches.dup
|
|
109
131
|
end
|
|
110
132
|
|
|
111
|
-
#
|
|
133
|
+
# Serialized pattern representation.
|
|
112
134
|
#
|
|
113
|
-
# @return [
|
|
114
|
-
def
|
|
115
|
-
|
|
116
|
-
pattern: @pattern.to_s,
|
|
117
|
-
matches: count,
|
|
118
|
-
scanned: @total_scanned,
|
|
119
|
-
match_rate: match_rate,
|
|
120
|
-
}
|
|
135
|
+
# @return [String] The pattern as a string
|
|
136
|
+
def pattern_to_s
|
|
137
|
+
@pattern.to_s
|
|
121
138
|
end
|
|
122
139
|
end
|
|
123
140
|
end
|
|
@@ -1,41 +1,60 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
3
5
|
module Omnizip
|
|
4
6
|
module Models
|
|
5
|
-
# Represents a performance optimization suggestion based on
|
|
6
|
-
|
|
7
|
+
# Represents a performance optimization suggestion based on
|
|
8
|
+
# profiling data.
|
|
9
|
+
#
|
|
10
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
11
|
+
# The priority_score key serializes the derived #priority_score
|
|
12
|
+
# method under a distinct attribute name.
|
|
13
|
+
class OptimizationSuggestion < Lutaml::Model::Serializable
|
|
7
14
|
SEVERITY_LEVELS = %i[low medium high critical].freeze
|
|
8
15
|
CATEGORIES = %i[
|
|
9
16
|
memory cpu hotpath algorithm io gc allocation concurrency
|
|
10
17
|
].freeze
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
attribute :title, :string
|
|
20
|
+
attribute :description, :string
|
|
21
|
+
attribute :severity, :symbol
|
|
22
|
+
attribute :category, :symbol
|
|
23
|
+
attribute :impact_estimate, :double
|
|
24
|
+
attribute :implementation_effort, :double
|
|
25
|
+
attribute :related_operations, :string, collection: true, default: []
|
|
26
|
+
attribute :code_locations, :string, collection: true, default: []
|
|
27
|
+
attribute :metrics, :hash, default: {}
|
|
28
|
+
|
|
29
|
+
attribute :priority, :double, method: :priority_score
|
|
30
|
+
|
|
31
|
+
key_value do
|
|
32
|
+
map "title", to: :title, render_default: true, render_nil: true
|
|
33
|
+
map "description", to: :description,
|
|
34
|
+
render_default: true, render_nil: true
|
|
35
|
+
map "severity", to: :severity, render_default: true, render_nil: true
|
|
36
|
+
map "category", to: :category, render_default: true, render_nil: true
|
|
37
|
+
map "impact_estimate", to: :impact_estimate,
|
|
38
|
+
render_default: true, render_nil: true
|
|
39
|
+
map "implementation_effort", to: :implementation_effort,
|
|
40
|
+
render_default: true, render_nil: true
|
|
41
|
+
map "priority_score", to: :priority,
|
|
42
|
+
render_default: true, render_nil: true
|
|
43
|
+
map "related_operations", to: :related_operations,
|
|
44
|
+
render_default: true, render_nil: true
|
|
45
|
+
map "code_locations", to: :code_locations,
|
|
46
|
+
render_default: true, render_nil: true
|
|
47
|
+
map "metrics", to: :metrics, render_default: true, render_nil: true
|
|
48
|
+
end
|
|
15
49
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
implementation_effort: nil,
|
|
23
|
-
related_operations: [],
|
|
24
|
-
code_locations: [],
|
|
25
|
-
metrics: {}
|
|
26
|
-
)
|
|
50
|
+
# Severity and category are validated after the framework
|
|
51
|
+
# constructor assigns the attributes. Empty-collection defaults
|
|
52
|
+
# are assigned explicitly (lutaml-model 0.8.x drops them).
|
|
53
|
+
def initialize(attrs = {})
|
|
54
|
+
super({ related_operations: [], code_locations: [],
|
|
55
|
+
metrics: {} }.merge(attrs))
|
|
27
56
|
validate_severity!(severity)
|
|
28
57
|
validate_category!(category)
|
|
29
|
-
|
|
30
|
-
@title = title
|
|
31
|
-
@description = description
|
|
32
|
-
@severity = severity
|
|
33
|
-
@category = category
|
|
34
|
-
@impact_estimate = impact_estimate
|
|
35
|
-
@implementation_effort = implementation_effort
|
|
36
|
-
@related_operations = related_operations
|
|
37
|
-
@code_locations = code_locations
|
|
38
|
-
@metrics = metrics
|
|
39
58
|
end
|
|
40
59
|
|
|
41
60
|
def critical?
|
|
@@ -54,21 +73,6 @@ module Omnizip
|
|
|
54
73
|
severity_weight * impact_weight * effort_weight
|
|
55
74
|
end
|
|
56
75
|
|
|
57
|
-
def to_h
|
|
58
|
-
{
|
|
59
|
-
title: title,
|
|
60
|
-
description: description,
|
|
61
|
-
severity: severity,
|
|
62
|
-
category: category,
|
|
63
|
-
impact_estimate: impact_estimate,
|
|
64
|
-
implementation_effort: implementation_effort,
|
|
65
|
-
priority_score: priority_score,
|
|
66
|
-
related_operations: related_operations,
|
|
67
|
-
code_locations: code_locations,
|
|
68
|
-
metrics: metrics,
|
|
69
|
-
}
|
|
70
|
-
end
|
|
71
|
-
|
|
72
76
|
private
|
|
73
77
|
|
|
74
78
|
def validate_severity!(severity)
|
|
@@ -1,35 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
2
4
|
|
|
3
5
|
module Omnizip
|
|
4
6
|
module Models
|
|
5
|
-
# Represents the performance characteristics of a profiled operation
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
# Represents the performance characteristics of a profiled operation.
|
|
8
|
+
#
|
|
9
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
10
|
+
# The derived-rate keys serialize the calculation methods; attribute
|
|
11
|
+
# names differ from the keys so generated readers do not shadow them.
|
|
12
|
+
class PerformanceResult < Lutaml::Model::Serializable
|
|
13
|
+
attribute :operation_name, :string
|
|
14
|
+
attribute :total_time, :double
|
|
15
|
+
attribute :cpu_time, :double
|
|
16
|
+
attribute :wall_time, :double
|
|
17
|
+
attribute :memory_allocated, :integer
|
|
18
|
+
attribute :memory_retained, :integer
|
|
19
|
+
attribute :object_allocations, :integer
|
|
20
|
+
attribute :gc_runs, :integer
|
|
21
|
+
attribute :call_count, :integer
|
|
22
|
+
attribute :timestamp, :date_time, default: -> { Time.now }
|
|
23
|
+
|
|
24
|
+
attribute :throughput, :double, method: :throughput_ops_per_second
|
|
25
|
+
attribute :average_time, :double, method: :average_time_per_operation
|
|
26
|
+
attribute :memory_per_op, :double, method: :memory_per_operation
|
|
27
|
+
attribute :pressure, :double, method: :gc_pressure
|
|
10
28
|
|
|
11
|
-
|
|
12
|
-
operation_name
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
key_value do
|
|
30
|
+
map "operation_name", to: :operation_name,
|
|
31
|
+
render_default: true, render_nil: true
|
|
32
|
+
map "total_time", to: :total_time,
|
|
33
|
+
render_default: true, render_nil: true
|
|
34
|
+
map "cpu_time", to: :cpu_time,
|
|
35
|
+
render_default: true, render_nil: true
|
|
36
|
+
map "wall_time", to: :wall_time,
|
|
37
|
+
render_default: true, render_nil: true
|
|
38
|
+
map "memory_allocated", to: :memory_allocated,
|
|
39
|
+
render_default: true, render_nil: true
|
|
40
|
+
map "memory_retained", to: :memory_retained,
|
|
41
|
+
render_default: true, render_nil: true
|
|
42
|
+
map "object_allocations", to: :object_allocations,
|
|
43
|
+
render_default: true, render_nil: true
|
|
44
|
+
map "gc_runs", to: :gc_runs,
|
|
45
|
+
render_default: true, render_nil: true
|
|
46
|
+
map "call_count", to: :call_count,
|
|
47
|
+
render_default: true, render_nil: true
|
|
48
|
+
map "throughput_ops_per_second", to: :throughput,
|
|
49
|
+
render_default: true, render_nil: true
|
|
50
|
+
map "average_time_per_operation", to: :average_time,
|
|
51
|
+
render_default: true, render_nil: true
|
|
52
|
+
map "memory_per_operation", to: :memory_per_op,
|
|
53
|
+
render_default: true, render_nil: true
|
|
54
|
+
map "gc_pressure", to: :pressure,
|
|
55
|
+
render_default: true, render_nil: true
|
|
56
|
+
map "timestamp", to: :timestamp,
|
|
57
|
+
render_default: true, render_nil: true
|
|
33
58
|
end
|
|
34
59
|
|
|
35
60
|
def throughput_ops_per_second
|
|
@@ -55,25 +80,6 @@ module Omnizip
|
|
|
55
80
|
|
|
56
81
|
gc_runs.to_f / total_time
|
|
57
82
|
end
|
|
58
|
-
|
|
59
|
-
def to_h
|
|
60
|
-
{
|
|
61
|
-
operation_name: operation_name,
|
|
62
|
-
total_time: total_time,
|
|
63
|
-
cpu_time: cpu_time,
|
|
64
|
-
wall_time: wall_time,
|
|
65
|
-
memory_allocated: memory_allocated,
|
|
66
|
-
memory_retained: memory_retained,
|
|
67
|
-
object_allocations: object_allocations,
|
|
68
|
-
gc_runs: gc_runs,
|
|
69
|
-
call_count: call_count,
|
|
70
|
-
throughput_ops_per_second: throughput_ops_per_second,
|
|
71
|
-
average_time_per_operation: average_time_per_operation,
|
|
72
|
-
memory_per_operation: memory_per_operation,
|
|
73
|
-
gc_pressure: gc_pressure,
|
|
74
|
-
timestamp: timestamp.iso8601,
|
|
75
|
-
}
|
|
76
|
-
end
|
|
77
83
|
end
|
|
78
84
|
end
|
|
79
85
|
end
|