Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 81 additions & 5 deletions sjsonnet/src/sjsonnet/Materializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -619,20 +619,96 @@ object Materializer extends Materializer {
}
i += 1
}
// Insertion sort by key name (optimal for 2-8 elements)
i = 1
while (i < visCount) {
sortInlineOrder(order, keys, visCount)
order
}

private def sortInlineOrder(order: Array[Int], keys: Array[String], len: Int): Unit = {
if (len <= 1) return
if (len <= 16) insertionSortInlineOrder(order, keys, 0, len - 1)
else quickSortInlineOrder(order, keys, 0, len - 1)
}

private def insertionSortInlineOrder(
order: Array[Int],
keys: Array[String],
left: Int,
right: Int): Unit = {
var i = left + 1
while (i <= right) {
val pivotIdx = order(i)
val pivotKey = keys(pivotIdx)
var j = i - 1
while (j >= 0 && Util.compareStringsByCodepoint(keys(order(j)), pivotKey) > 0) {
while (j >= left && Util.compareStringsByCodepoint(keys(order(j)), pivotKey) > 0) {
order(j + 1) = order(j)
j -= 1
}
order(j + 1) = pivotIdx
i += 1
}
order
}

private def quickSortInlineOrder(
order: Array[Int],
keys: Array[String],
left0: Int,
right0: Int): Unit = {
var left = left0
var right = right0
while (right - left > 16) {
val pivotKey = medianOfThreeKey(order, keys, left, right)
var i = left
var j = right
while (i <= j) {
while (Util.compareStringsByCodepoint(keys(order(i)), pivotKey) < 0) i += 1
while (Util.compareStringsByCodepoint(keys(order(j)), pivotKey) > 0) j -= 1
if (i <= j) {
val tmp = order(i)
order(i) = order(j)
order(j) = tmp
i += 1
j -= 1
}
}
if (j - left < right - i) {
if (left < j) quickSortInlineOrder(order, keys, left, j)
left = i
} else {
if (i < right) quickSortInlineOrder(order, keys, i, right)
right = j
}
}
insertionSortInlineOrder(order, keys, left, right)
}

/**
* Median-of-three pivot selection for [[quickSortInlineOrder]]. Returns the median key among
* `keys(order(left))`, `keys(order(mid))`, and `keys(order(right))` (where `mid = (left + right)
* >>> 1`). Compared to a fixed mid-element pivot, this reduces worst-case behaviour on inputs
* that are already sorted, reverse-sorted, or contain runs — patterns that occur frequently in
* Jsonnet object key sets.
*/
private def medianOfThreeKey(
order: Array[Int],
keys: Array[String],
left: Int,
right: Int): String = {
val mid = (left + right) >>> 1
val a = keys(order(left))
val b = keys(order(mid))
val c = keys(order(right))
val ab = Util.compareStringsByCodepoint(a, b)
val ac = Util.compareStringsByCodepoint(a, c)
val bc = Util.compareStringsByCodepoint(b, c)
if (ab <= 0) {
if (bc <= 0) b // a <= b <= c
else if (ac <= 0) c // a <= c < b
else a // c < a <= b
} else {
if (ac <= 0) a // b < a <= c
else if (bc <= 0) c // b <= c < a
else b // c < b < a
}
}

/**
Expand Down
Loading