Skip to content

Commit 09d70a4

Browse files
skorotkovalex-plekhanov
authored andcommitted
IGNITE-25736 Speed up warmup running in several threads - Fixes #12153.
Signed-off-by: Aleksey Plekhanov <[email protected]>
1 parent 2572baf commit 09d70a4

File tree

4 files changed

+96
-27
lines changed

4 files changed

+96
-27
lines changed

modules/core/src/main/java/org/apache/ignite/internal/processors/cache/warmup/LoadAllWarmUpStrategy.java

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,27 @@
2222
import java.util.LinkedHashMap;
2323
import java.util.List;
2424
import java.util.Map;
25+
import java.util.concurrent.atomic.AtomicLong;
2526
import java.util.function.Supplier;
2627
import org.apache.ignite.IgniteCheckedException;
2728
import org.apache.ignite.IgniteLogger;
2829
import org.apache.ignite.configuration.DataRegionConfiguration;
2930
import org.apache.ignite.configuration.LoadAllWarmUpConfiguration;
31+
import org.apache.ignite.internal.GridKernalContext;
32+
import org.apache.ignite.internal.managers.communication.GridIoPolicy;
3033
import org.apache.ignite.internal.processors.cache.CacheGroupContext;
3134
import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
3235
import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition;
3336
import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
3437
import org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryEx;
3538
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
3639
import org.apache.ignite.internal.util.typedef.internal.S;
40+
import org.apache.ignite.internal.util.typedef.internal.U;
3741

42+
import static java.util.stream.Collectors.averagingInt;
3843
import static java.util.stream.Collectors.toList;
3944
import static org.apache.ignite.internal.pagemem.PageIdAllocator.INDEX_PARTITION;
45+
import static org.apache.ignite.internal.util.IgniteUtils.doInParallel;
4046

4147
/**
4248
* "Load all" warm-up strategy, which loads pages to persistent data region
@@ -99,12 +105,32 @@ public LoadAllWarmUpStrategy(IgniteLogger log, Supplier<Collection<CacheGroupCon
99105
loadDataInfo.keySet().stream().map(CacheGroupContext::cacheOrGroupName).collect(toList()) + ']');
100106
}
101107

102-
long loadedPageCnt = 0;
108+
AtomicLong loadedPageCnt = new AtomicLong();
103109

104110
for (Map.Entry<CacheGroupContext, List<LoadPartition>> e : loadDataInfo.entrySet()) {
105111
CacheGroupContext grp = e.getKey();
106112
List<LoadPartition> parts = e.getValue();
107113

114+
LoadPartition idxPart = parts.get(0);
115+
116+
int avgPartPagesCnt = parts.stream()
117+
.filter(p -> p.part() != INDEX_PARTITION)
118+
.map(LoadPartition::pages)
119+
.collect(averagingInt(i -> i)).intValue();
120+
121+
if (avgPartPagesCnt != 0 && idxPart.pages() > avgPartPagesCnt) {
122+
// Split index partition into chunks to balance threads load. It's needed since
123+
// index partition is usually much larger than the data one if indexing is enabled.
124+
List<LoadPartition> newParts = new ArrayList<>(idxPart.pages() / avgPartPagesCnt + parts.size());
125+
126+
for (int i = 0; i < idxPart.pages(); i += avgPartPagesCnt)
127+
newParts.add(new LoadPartition(idxPart.part(), Math.min(idxPart.pages() - i, avgPartPagesCnt), i));
128+
129+
newParts.addAll(parts.subList(1, parts.size()));
130+
131+
parts = newParts;
132+
}
133+
108134
if (log.isInfoEnabled()) {
109135
log.info("Start warm-up cache group, with estimated statistics [name=" + grp.cacheOrGroupName()
110136
+ ", partCnt=" + parts.size() + ", pageCnt="
@@ -113,31 +139,42 @@ public LoadAllWarmUpStrategy(IgniteLogger log, Supplier<Collection<CacheGroupCon
113139

114140
PageMemoryEx pageMemEx = (PageMemoryEx)region.pageMemory();
115141

116-
for (LoadPartition part : parts) {
117-
long pageId = pageMemEx.partitionMetaPageId(grp.groupId(), part.part());
142+
GridKernalContext ctx = grp.shared().kernalContext();
118143

119-
for (int i = 0; i < part.pages(); i++, pageId++, loadedPageCnt++) {
120-
if (stop) {
121-
if (log.isInfoEnabled()) {
122-
log.info("Stop warm-up cache group with loaded statistics [name="
123-
+ grp.cacheOrGroupName() + ", pageCnt=" + loadedPageCnt
124-
+ ", remainingPageCnt=" + (availableLoadPageCnt - loadedPageCnt) + ']');
125-
}
144+
doInParallel(
145+
U.availableThreadCount(ctx, GridIoPolicy.SYSTEM_POOL, 2),
146+
ctx.pools().getSystemExecutorService(),
147+
parts,
148+
part -> {
149+
long pageId = pageMemEx.partitionMetaPageId(grp.groupId(), part.part());
126150

127-
return;
128-
}
151+
pageId += part.startPageIdx();
129152

130-
long pagePtr = -1;
153+
for (int i = 0; i < part.pages(); i++, pageId++, loadedPageCnt.incrementAndGet()) {
154+
if (stop) {
155+
if (log.isInfoEnabled()) {
156+
log.info("Stop warm-up cache group with loaded statistics [name="
157+
+ grp.cacheOrGroupName() + ", pageCnt=" + loadedPageCnt.get()
158+
+ ", remainingPageCnt=" + (availableLoadPageCnt - loadedPageCnt.get()) + ']');
159+
}
131160

132-
try {
133-
pagePtr = pageMemEx.acquirePage(grp.groupId(), pageId);
134-
}
135-
finally {
136-
if (pagePtr != -1)
137-
pageMemEx.releasePage(grp.groupId(), pageId, pagePtr);
161+
return null;
162+
}
163+
164+
long pagePtr = -1;
165+
166+
try {
167+
pagePtr = pageMemEx.acquirePage(grp.groupId(), pageId);
168+
}
169+
finally {
170+
if (pagePtr != -1)
171+
pageMemEx.releasePage(grp.groupId(), pageId, pagePtr);
172+
}
138173
}
174+
175+
return null;
139176
}
140-
}
177+
);
141178
}
142179
}
143180

@@ -194,14 +231,14 @@ protected Map<CacheGroupContext, List<LoadPartition>> loadDataInfo(
194231
for (int j = -1; j < locParts.size() && availableLoadPageCnt > 0; j++) {
195232
int p = j == -1 ? INDEX_PARTITION : locParts.get(j).id();
196233

197-
long partPageCnt = grp.shared().pageStore().pages(grp.groupId(), p);
234+
int partPageCnt = grp.shared().pageStore().pages(grp.groupId(), p);
198235

199236
if (partPageCnt > 0) {
200-
long pageCnt = (availableLoadPageCnt - partPageCnt) >= 0 ? partPageCnt : availableLoadPageCnt;
237+
int pageCnt = (availableLoadPageCnt - partPageCnt) >= 0 ? partPageCnt : (int)availableLoadPageCnt;
201238

202239
availableLoadPageCnt -= pageCnt;
203240

204-
loadableGrps.computeIfAbsent(grp, grpCtx -> new ArrayList<>()).add(new LoadPartition(p, pageCnt));
241+
loadableGrps.computeIfAbsent(grp, grpCtx -> new ArrayList<>()).add(new LoadPartition(p, pageCnt, 0));
205242
}
206243
}
207244
}
@@ -217,20 +254,25 @@ static class LoadPartition {
217254
private final int part;
218255

219256
/** Number of pages to load. */
220-
private final long pages;
257+
private final int pages;
258+
259+
/** Index of first page to load. */
260+
private final int startPageIdx;
221261

222262
/**
223263
* Constructor.
224264
*
225265
* @param part Partition id.
226266
* @param pages Number of pages to load.
267+
* @param startPageIdx Index of first page to load.
227268
*/
228-
public LoadPartition(int part, long pages) {
269+
public LoadPartition(int part, int pages, int startPageIdx) {
229270
assert part >= 0 : "Partition id cannot be negative.";
230271
assert pages > 0 : "Number of pages to load must be greater than zero.";
231272

232273
this.part = part;
233274
this.pages = pages;
275+
this.startPageIdx = startPageIdx;
234276
}
235277

236278
/**
@@ -247,10 +289,19 @@ public int part() {
247289
*
248290
* @return Number of pages to load.
249291
*/
250-
public long pages() {
292+
public int pages() {
251293
return pages;
252294
}
253295

296+
/**
297+
* Return index of first page to load.
298+
*
299+
* @return Index of first page to load.
300+
*/
301+
public int startPageIdx() {
302+
return startPageIdx;
303+
}
304+
254305
/** {@inheritDoc} */
255306
@Override public String toString() {
256307
return S.toString(LoadPartition.class, this);

modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/data_storage.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
from typing import NamedTuple
2121

22+
from ignitetest.utils.bean import Bean
23+
2224

2325
class DataRegionConfiguration(NamedTuple):
2426
"""
@@ -33,6 +35,7 @@ class DataRegionConfiguration(NamedTuple):
3335
metrics_enabled: bool = True
3436
metrics_rate_time_interval: int = None
3537
checkpoint_page_buffer_size: int = None
38+
warm_up_configuration: Bean = None
3639

3740

3841
class DataStorageConfiguration(NamedTuple):
@@ -60,3 +63,4 @@ class DataStorageConfiguration(NamedTuple):
6063
write_recovery_data_on_checkpoint: bool = None
6164
checkpoint_recovery_data_compression: str = None
6265
checkpoint_recovery_data_compression_level: int = None
66+
default_warm_up_configuration: Bean = None

modules/ducktests/tests/ignitetest/services/utils/templates/datastorage_macro.j2

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
limitations under the License.
1616
#}
1717

18+
{% import 'misc_macro.j2' as misc_utils %}
19+
1820
{% macro data_storage(config) %}
1921
{% if config %}
2022
<property name="dataStorageConfiguration">
@@ -33,6 +35,10 @@
3335
{% endfor %}
3436
</list>
3537
</property>
38+
{% elif name == 'default_warm_up_configuration' %}
39+
<property name="defaultWarmUpConfiguration">
40+
{{ misc_utils.bean(value) }}
41+
</property>
3642
{% else %}
3743
<property name="{{ name | snake_to_camel }}" value="{{ value }}"/>
3844
{% endif %}
@@ -47,7 +53,13 @@
4753
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
4854
{% for name, value in config._asdict().items() %}
4955
{% if value != None %}
50-
<property name="{{ name | snake_to_camel }}" value="{{ value }}"/>
56+
{% if name == 'warm_up_configuration' %}
57+
<property name="warmUpConfiguration">
58+
{{ misc_utils.bean(value) }}
59+
</property>
60+
{% else %}
61+
<property name="{{ name | snake_to_camel }}" value="{{ value }}"/>
62+
{% endif %}
5163
{% endif %}
5264
{% endfor %}
5365
</bean>

modules/indexing/src/test/java/org/apache/ignite/testsuites/IgnitePdsWithIndexingTestSuite.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.ignite.internal.processors.cache.persistence.db.IndexingMultithreadedLoadContinuousRestartTest;
3333
import org.apache.ignite.internal.processors.cache.persistence.db.LongDestroyDurableBackgroundTaskTest;
3434
import org.apache.ignite.internal.processors.cache.persistence.db.MultipleParallelCacheDeleteDeadlockTest;
35+
import org.apache.ignite.internal.processors.cache.warmup.LoadAllWarmUpStrategySelfTest;
3536
import org.apache.ignite.internal.processors.database.IgniteDbMultiNodeWithIndexingPutGetTest;
3637
import org.apache.ignite.internal.processors.database.IgniteDbSingleNodeWithIndexingPutGetTest;
3738
import org.apache.ignite.internal.processors.database.IgniteDbSingleNodeWithIndexingWalRestoreTest;
@@ -75,6 +76,7 @@
7576
DropIndexTest.class,
7677
MaintenanceRebuildIndexUtilsSelfTest.class,
7778
IndexWithSameNameH2Test.class,
79+
LoadAllWarmUpStrategySelfTest.class
7880
})
7981
public class IgnitePdsWithIndexingTestSuite {
8082
}

0 commit comments

Comments
 (0)