From 9990d8ab85d794e33e72e51e25ec71ef867f3e77 Mon Sep 17 00:00:00 2001 From: Phil Ewels Date: Thu, 21 May 2026 02:08:01 +0200 Subject: [PATCH] Replace .toCharArray() in module hot paths with String.charAt() Each per-sequence module called String.toCharArray() once per read, allocating a fresh char[] each time. Switching to a String reference plus charAt() removes that allocation without changing the algorithm. PerSequenceGCContent#truncateSequence now returns the truncated String directly so the per-read char[] in the no-truncation path also goes away. Affects: BasicStats, NContent, PerBaseQualityScores, PerBaseSequenceContent, PerSequenceGCContent, PerSequenceQualityScores, PerTileQualityScores. Co-Authored-By: Paolo Di Tommaso --- uk/ac/babraham/FastQC/Modules/BasicStats.java | 17 ++++++----- uk/ac/babraham/FastQC/Modules/NContent.java | 13 ++++---- .../FastQC/Modules/PerBaseQualityScores.java | 13 ++++---- .../Modules/PerBaseSequenceContent.java | 26 ++++++++-------- .../FastQC/Modules/PerSequenceGCContent.java | 30 ++++++++++--------- .../Modules/PerSequenceQualityScores.java | 16 +++++----- .../FastQC/Modules/PerTileQualityScores.java | 13 ++++---- 7 files changed, 70 insertions(+), 58 deletions(-) diff --git a/uk/ac/babraham/FastQC/Modules/BasicStats.java b/uk/ac/babraham/FastQC/Modules/BasicStats.java index bb06b9c..9e37a1a 100644 --- a/uk/ac/babraham/FastQC/Modules/BasicStats.java +++ b/uk/ac/babraham/FastQC/Modules/BasicStats.java @@ -123,9 +123,10 @@ public void processSequence(Sequence sequence) { if (sequence.getSequence().length() > maxLength) maxLength = sequence.getSequence().length(); } - char [] chars = sequence.getSequence().toCharArray(); - for (int c=0;c= cachedModels.length) { + if (seqLen >= cachedModels.length) { // We need to extend the length of cached models - GCModel [] longerModels = new GCModel[seq.length+1]; + GCModel [] longerModels = new GCModel[seqLen+1]; for (int i=0;i 1000) { int length = (seq.length()/1000)*1000; - return seq.substring(0, length).toCharArray(); + return seq.substring(0, length); } if (seq.length() > 100) { int length = (seq.length()/100)*100; - return seq.substring(0, length).toCharArray(); + return seq.substring(0, length); } - return seq.toCharArray(); + return seq; } diff --git a/uk/ac/babraham/FastQC/Modules/PerSequenceQualityScores.java b/uk/ac/babraham/FastQC/Modules/PerSequenceQualityScores.java index 61661e5..276ac6b 100644 --- a/uk/ac/babraham/FastQC/Modules/PerSequenceQualityScores.java +++ b/uk/ac/babraham/FastQC/Modules/PerSequenceQualityScores.java @@ -88,18 +88,20 @@ private synchronized void calculateDistribution () { public void processSequence(Sequence sequence) { - char [] seq = sequence.getQualityString().toCharArray(); + String qual = sequence.getQualityString(); + int qualLen = qual.length(); int averageQuality = 0; - for (int i=0;i 0) { - averageQuality /= seq.length; + if (qualLen > 0) { + averageQuality /= qualLen; if (averageScoreCounts.containsKey(averageQuality)) { long currentCount = averageScoreCounts.get(averageQuality); diff --git a/uk/ac/babraham/FastQC/Modules/PerTileQualityScores.java b/uk/ac/babraham/FastQC/Modules/PerTileQualityScores.java index 41afd71..6f344f6 100644 --- a/uk/ac/babraham/FastQC/Modules/PerTileQualityScores.java +++ b/uk/ac/babraham/FastQC/Modules/PerTileQualityScores.java @@ -256,15 +256,16 @@ else if (splitID.length >=5) { return; } - char [] qual = sequence.getQualityString().toCharArray(); - if (currentLength < qual.length) { + String qual = sequence.getQualityString(); + int qualLen = qual.length(); + if (currentLength < qualLen) { Iterator tiles = perTileQualityCounts.keySet().iterator(); while (tiles.hasNext()) { int thisTile = tiles.next(); QualityCount [] qualityCounts = perTileQualityCounts.get(thisTile); - QualityCount [] qualityCountsNew = new QualityCount[qual.length]; + QualityCount [] qualityCountsNew = new QualityCount[qualLen]; for (int i=0;i=5) { perTileQualityCounts.put(thisTile, qualityCountsNew); } - currentLength = qual.length; + currentLength = qualLen; } @@ -300,8 +301,8 @@ else if (splitID.length >=5) { QualityCount [] qualityCounts = perTileQualityCounts.get(tile); - for (int i=0;i