wave7: 433/194 — kafka/flink/pulsar, spring/micronaut/quarkus, nginx/haproxy/traefik, linux/nomad/consul, numpy/pandas/sklearn, ES/OS/pg/sqlite/rustc/cargo
This commit is contained in:
parent
3735145aa5
commit
5fe6da7cc2
69 changed files with 6793 additions and 32 deletions
|
|
@ -0,0 +1,49 @@
|
|||
# pulsar-0001: GetTopicsResult.getTopics() — ArrayList.contains() inside dedup for loop
|
||||
|
||||
## Defect ID
|
||||
pulsar-0001
|
||||
|
||||
## File:Line
|
||||
`pulsar-common/src/main/java/org/apache/pulsar/common/lookup/GetTopicsResult.java:117`
|
||||
|
||||
## Description
|
||||
`getTopics()` deduplicates partitioned topic names:
|
||||
|
||||
```java
|
||||
List<String> grouped = new ArrayList<>();
|
||||
for (String topic : nonPartitionedOrPartitionTopics) { // O(N)
|
||||
String partitionedTopic = TopicName.get(topic).getPartitionedTopicName();
|
||||
if (!grouped.contains(partitionedTopic)) { // O(N) linear scan
|
||||
grouped.add(partitionedTopic);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`grouped` is an `ArrayList<String>`. Each `.contains()` is O(N). Total: O(N²).
|
||||
|
||||
This method is called on every consumer subscription lookup, broker topic listing,
|
||||
and namespace topic query. For a namespace with 1,000 topic partitions (e.g.,
|
||||
a topic with 1000 partitions), this scans up to 1000×1000 = 1M comparisons
|
||||
instead of 1000 with a `LinkedHashSet`.
|
||||
|
||||
## Complexity
|
||||
- Slow: O(N²) — ArrayList.contains() = O(N)
|
||||
- Fast: O(N) — LinkedHashSet.add() = O(1) with preserved insertion order
|
||||
|
||||
## Severity
|
||||
HIGH
|
||||
|
||||
## Speedup Estimate
|
||||
~N× improvement = 1000x at N=1000 partitions.
|
||||
|
||||
## Fix
|
||||
Replace `ArrayList` with `LinkedHashSet<String>` to preserve order while giving
|
||||
O(1) dedup, then convert to `List` for the return type:
|
||||
|
||||
```java
|
||||
LinkedHashSet<String> grouped = new LinkedHashSet<>();
|
||||
for (String topic : nonPartitionedOrPartitionTopics) {
|
||||
grouped.add(TopicName.get(topic).getPartitionedTopicName());
|
||||
}
|
||||
topics = new ArrayList<>(grouped);
|
||||
```
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# pulsar-0002: JavaInstanceRunnable — List.contains() inside config key validation loop
|
||||
|
||||
## Defect ID
|
||||
pulsar-0002
|
||||
|
||||
## File:Line
|
||||
`pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceRunnable.java:987`
|
||||
|
||||
## Description
|
||||
In `setupConfig()`:
|
||||
|
||||
```java
|
||||
final List<String> allFields = BeanPropertiesReader.getBeanProperties(configClass); // List<String>
|
||||
for (String s : config.keySet()) { // O(K) iterations over config keys
|
||||
if (!allFields.contains(s)) { // O(F) linear scan over field names
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`allFields` is a `List<String>` returned by `BeanPropertiesReader.getBeanProperties()`.
|
||||
Each `.contains()` is O(F) where F = number of bean fields. Total: O(K × F).
|
||||
|
||||
While this runs at function startup (not hot per-message), it runs once per function
|
||||
instance initialization. For a config class with 200 fields and 150 config keys,
|
||||
this is 30,000 comparisons vs 350 with a HashSet.
|
||||
|
||||
## Complexity
|
||||
- Slow: O(K × F) — List.contains() = O(F)
|
||||
- Fast: O(K) — HashSet.contains() = O(1)
|
||||
|
||||
## Severity
|
||||
MEDIUM
|
||||
|
||||
## Speedup Estimate
|
||||
~F× improvement = 200x at F=200 fields.
|
||||
|
||||
## Fix
|
||||
Convert `allFields` to `HashSet<String>` immediately after retrieval:
|
||||
|
||||
```java
|
||||
Set<String> allFieldsSet = new HashSet<>(BeanPropertiesReader.getBeanProperties(configClass));
|
||||
for (String s : config.keySet()) {
|
||||
if (!allFieldsSet.contains(s)) { ... }
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue