{
  "id": 5810379,
  "title": "Fifty seconds for half a megabyte: the optimisation that fixed the constant, not the order",
  "url": "https://urgent.news/2026/09/05/fifty-seconds-for-half-a-megabyte-the-optimisation-that-fixed-the",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-05T18:29:16.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/isazajuancarlos/fifty-seconds-for-half-a-megabyte-the-optimisation-that-fixed-the-constant-not-the-order-2afe"
  },
  "original_language": "en",
  "account": "A cryptography library experienced a significant performance bottleneck: encrypting half a megabyte took fifty seconds. Despite passing numerous tests, the underlying issue persisted. The culprit was an optimization that improved the constant runtime but did not change the overall order of growth—leading to a quadratic algorithm, which quadrupled execution time each time the input size doubled. This deceptive optimisation was well-documented and even mentioned in the code's comments, suggesting the problem was solved, when in fact it was only masking the inefficiency. The encryption process converted the entire message into a single large integer and then divided it repeatedly to extract digits, a method akin to manually converting a base-10 number to base 2. Rather than processing one digit at a time, the code efficiently divided by the largest power of the base that fit into a machine word, extracting nine digits per pass instead of one. However, the comment explaining this optimisation erroneously suggested it would be quadratic, misguiding readers into believing the issue was resolved. The optimisation provided a fourfold speedup, but the true time complexity remained quadratic, meaning that larger inputs would suffer even more. The measurement confirmed this, with a ten-megabyte encryption taking approximately five and a half hours—far beyond acceptable performance. The solution was a classical algorithm known as divide-and-conquer radix conversion, which splits the number into halves, reducing the number of divisions required. By combining this approach with efficient big-integer multiplication, the time per doubling dropped from four to approximately 2.82. This optimization was only effective if the big-integer library utilized sub-quadratic division; otherwise, the algorithm would still be quadratic, albeit with a worse constant factor. The error lay in the misleading comment about the constant optimization and the absence of a metric to detect the quadratic nature of the algorithm. The fix was straightforward: verifying that the division operation was sub-quadratic before implementing the algorithm. This oversight prevented the algorithm from being more elegant, harder to comprehend, and slower. Had the library used Burnikel-Ziegler recursive division, the improvement would have been even more pronounced. To prevent similar issues in future projects, it's crucial to measure not just the constant but the overall order of growth by comparing input sizes and the resulting execution times. A simple check of whether doubling the input size doubles the time (linear), quadruples it (quadratic), or increases by approximately 2.8 (indicating a tree-based approach with fast multiplication) can reveal the true nature of the algorithm's performance. Implementing a test that flags such regressions would safeguard against similar deceptive optimizations in the future.",
  "summary": "A cryptography library had a bottleneck no test could see : encrypting half a megabyte took fifty seconds. Every test passed. They had been passing for months. The cause is a trap that keeps recurring: a correct, well-documented optimisation that fixes the constant and not the order — and whose comment, precisely because it is well written, convinces the reader the problem is already solved. What…",
  "key_points": [
    "Encryption process converted message to large integer, then divided repeatedly",
    "Optimisation improved constant runtime but didn't change order of growth",
    "Quadratic algorithm quadrupled execution time with doubled input size"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}