wave9 complete: 458/207 — airflow/argo/pytorch-0003/tf/jax/pyg/grpc/thrift + graphhopper/valhalla
This commit is contained in:
parent
81bc62b9cb
commit
ab10b2f555
22 changed files with 2889 additions and 16 deletions
249
defects/thrift/unit/ThriftStructMembersAlgorithm.java
Normal file
249
defects/thrift/unit/ThriftStructMembersAlgorithm.java
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* thrift-0001: t_cpp_generator is_struct_storage_not_throwing() std::find O(M^2) → O(1)
|
||||
*
|
||||
* Simulates the defective pattern from Apache Thrift's C++ generator:
|
||||
* is_struct_storage_not_throwing() flattens nested struct members using
|
||||
* std::find on a vector<t_field*> for deduplication.
|
||||
* When N nested structs each contribute M fields, total ops = O(N×M×total).
|
||||
*
|
||||
* Fixed: std::unordered_set<t_field*> for O(1) membership test.
|
||||
*
|
||||
* Run: javac -d . ThriftStructMembersAlgorithm.java && java unit.ThriftStructMembersAlgorithm
|
||||
*/
|
||||
public class ThriftStructMembersAlgorithm {
|
||||
|
||||
// Simulated t_field* — each instance is a unique pointer
|
||||
static class Field {
|
||||
final String name;
|
||||
final boolean isStruct;
|
||||
final List<Field> nestedFields;
|
||||
|
||||
Field(String name) {
|
||||
this.name = name;
|
||||
this.isStruct = false;
|
||||
this.nestedFields = null;
|
||||
}
|
||||
|
||||
Field(String name, List<Field> nested) {
|
||||
this.name = name;
|
||||
this.isStruct = true;
|
||||
this.nestedFields = nested;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Result ----
|
||||
static class Result {
|
||||
final long ops;
|
||||
final boolean noexcept;
|
||||
Result(long ops, boolean noexcept) {
|
||||
this.ops = ops;
|
||||
this.noexcept = noexcept;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Defective: std::find on vector — O(M) per dedup check ----
|
||||
static class DefectiveStructAnalyzer {
|
||||
long opCount = 0;
|
||||
|
||||
boolean isStructStorageNotThrowing(List<Field> topLevelMembers) {
|
||||
List<Field> members = new ArrayList<>(topLevelMembers);
|
||||
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
Field field = members.get(i);
|
||||
if (field.isStruct && field.nestedFields != null) {
|
||||
for (Field nested : field.nestedFields) {
|
||||
// std::find: O(members.size()) scan
|
||||
boolean found = false;
|
||||
for (Field m : members) {
|
||||
opCount++;
|
||||
if (m == nested) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
members.add(nested);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Simulate non-struct field checks (constant work)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Fixed: unordered_set O(1) dedup ----
|
||||
static class FixedStructAnalyzer {
|
||||
long opCount = 0;
|
||||
|
||||
boolean isStructStorageNotThrowing(List<Field> topLevelMembers) {
|
||||
List<Field> members = new ArrayList<>(topLevelMembers);
|
||||
Set<Field> seen = new IdentityHashMap<Field, Boolean>()
|
||||
{{ for (Field f : members) put(f, Boolean.TRUE); }}.keySet();
|
||||
// Use IdentityHashMap to simulate pointer-based set (reference equality)
|
||||
Set<Field> seenSet = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
seenSet.addAll(topLevelMembers);
|
||||
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
Field field = members.get(i);
|
||||
if (field.isStruct && field.nestedFields != null) {
|
||||
for (Field nested : field.nestedFields) {
|
||||
opCount++; // O(1) hash lookup
|
||||
if (!seenSet.contains(nested)) {
|
||||
members.add(nested);
|
||||
seenSet.add(nested);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- check helper ----
|
||||
static int passed = 0;
|
||||
static int total = 0;
|
||||
|
||||
static void check(String name, boolean condition) {
|
||||
total++;
|
||||
if (condition) {
|
||||
passed++;
|
||||
System.out.println(" PASS: " + name);
|
||||
} else {
|
||||
System.out.println(" FAIL: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a struct with N fields, each of which is a struct with M nested fields
|
||||
static List<Field> buildNestedStruct(int topN, int nestedM, int nestDepth) {
|
||||
if (nestDepth == 0) {
|
||||
List<Field> leaves = new ArrayList<>();
|
||||
for (int i = 0; i < nestedM; i++) leaves.add(new Field("leaf_" + i));
|
||||
return leaves;
|
||||
}
|
||||
List<Field> inner = buildNestedStruct(topN, nestedM, nestDepth - 1);
|
||||
List<Field> result = new ArrayList<>();
|
||||
for (int i = 0; i < topN; i++) {
|
||||
result.add(new Field("struct_" + nestDepth + "_" + i, new ArrayList<>(inner)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("thrift-0001: is_struct_storage_not_throwing std::find O(M^2) -> O(1)");
|
||||
System.out.println();
|
||||
|
||||
// ---- Test 1: Simple flat struct (no nesting) — both same ----
|
||||
{
|
||||
List<Field> members = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) members.add(new Field("field_" + i));
|
||||
|
||||
DefectiveStructAnalyzer slow = new DefectiveStructAnalyzer();
|
||||
FixedStructAnalyzer fast = new FixedStructAnalyzer();
|
||||
|
||||
slow.isStructStorageNotThrowing(members);
|
||||
fast.isStructStorageNotThrowing(members);
|
||||
|
||||
System.out.println("Test 1: flat struct, 10 fields (no nesting)");
|
||||
System.out.println(" Slow ops: " + slow.opCount + ", Fast ops: " + fast.opCount);
|
||||
check("both handle flat struct (ops >= 0)", slow.opCount >= 0 && fast.opCount >= 0);
|
||||
}
|
||||
|
||||
// ---- Test 2: Nested struct (5 top-level, each nested 10 fields) ----
|
||||
{
|
||||
// Build shared nested fields (same pointers = dedup matters)
|
||||
List<Field> sharedNested = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) sharedNested.add(new Field("nested_" + i));
|
||||
|
||||
List<Field> members = new ArrayList<>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
members.add(new Field("struct_" + i, sharedNested));
|
||||
}
|
||||
|
||||
DefectiveStructAnalyzer slow = new DefectiveStructAnalyzer();
|
||||
FixedStructAnalyzer fast = new FixedStructAnalyzer();
|
||||
|
||||
slow.isStructStorageNotThrowing(members);
|
||||
fast.isStructStorageNotThrowing(members);
|
||||
|
||||
System.out.println("Test 2: 5 struct fields each with 10 nested fields");
|
||||
System.out.println(" Slow ops: " + slow.opCount + ", Fast ops: " + fast.opCount);
|
||||
check("slow > fast (vector scan > hash set)", slow.opCount >= fast.opCount);
|
||||
}
|
||||
|
||||
// ---- Test 3: Large nested struct — O(M^2) regime ----
|
||||
{
|
||||
// 20 struct fields each with 30 unique nested fields
|
||||
int topN = 20, nestedM = 30;
|
||||
List<Field> members = new ArrayList<>();
|
||||
for (int i = 0; i < topN; i++) {
|
||||
List<Field> nested = new ArrayList<>();
|
||||
for (int j = 0; j < nestedM; j++) nested.add(new Field("n_" + i + "_" + j));
|
||||
members.add(new Field("s_" + i, nested));
|
||||
}
|
||||
|
||||
DefectiveStructAnalyzer slow = new DefectiveStructAnalyzer();
|
||||
FixedStructAnalyzer fast = new FixedStructAnalyzer();
|
||||
|
||||
slow.isStructStorageNotThrowing(members);
|
||||
fast.isStructStorageNotThrowing(members);
|
||||
|
||||
System.out.println("Test 3: 20 struct fields × 30 nested fields each (M=" + topN*nestedM + ")");
|
||||
System.out.println(" Slow ops: " + slow.opCount + ", Fast ops: " + fast.opCount);
|
||||
double ratio = (double) slow.opCount / Math.max(fast.opCount, 1);
|
||||
System.out.printf(" Ratio slow/fast: %.1fx%n", ratio);
|
||||
check("slow > 5x fast for M=600", ratio > 5.0);
|
||||
}
|
||||
|
||||
// ---- Test 4: O(M^2) scaling — doubling members quadruples slow ops ----
|
||||
{
|
||||
// All unique nested fields → no early termination in std::find
|
||||
int[] sizes = {10, 20};
|
||||
long[] slowOps = new long[2];
|
||||
for (int s = 0; s < 2; s++) {
|
||||
int N = sizes[s];
|
||||
List<Field> members = new ArrayList<>();
|
||||
for (int i = 0; i < N; i++) {
|
||||
List<Field> nested = new ArrayList<>();
|
||||
for (int j = 0; j < N; j++) nested.add(new Field("n_" + i + "_" + j));
|
||||
members.add(new Field("struct_" + i, nested));
|
||||
}
|
||||
DefectiveStructAnalyzer slow = new DefectiveStructAnalyzer();
|
||||
slow.isStructStorageNotThrowing(members);
|
||||
slowOps[s] = slow.opCount;
|
||||
}
|
||||
System.out.println("Test 4: O(M^2) scaling");
|
||||
System.out.println(" N=10 ops: " + slowOps[0]);
|
||||
System.out.println(" N=20 ops: " + slowOps[1]);
|
||||
double ratio = (double) slowOps[1] / slowOps[0];
|
||||
System.out.printf(" Scaling: %.2fx (expect >3x for O(M^2))%n", ratio);
|
||||
check("ops grow super-linearly when N doubled (>3x)", ratio > 3.0);
|
||||
}
|
||||
|
||||
// ---- Test 5: Correctness — same result (noexcept) ----
|
||||
{
|
||||
List<Field> nested = Arrays.asList(new Field("x"), new Field("y"));
|
||||
List<Field> members = Arrays.asList(
|
||||
new Field("a", nested),
|
||||
new Field("b", nested),
|
||||
new Field("c")
|
||||
);
|
||||
|
||||
DefectiveStructAnalyzer slow = new DefectiveStructAnalyzer();
|
||||
FixedStructAnalyzer fast = new FixedStructAnalyzer();
|
||||
|
||||
boolean slowResult = slow.isStructStorageNotThrowing(members);
|
||||
boolean fastResult = fast.isStructStorageNotThrowing(members);
|
||||
|
||||
System.out.println("Test 5: correctness — both return same noexcept result");
|
||||
check("slow and fast return same result", slowResult == fastResult);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println(passed + "/" + total + " PASS");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue