@@ -364,8 +364,13 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
364
364
enum class ETasteResult : i8 {
365
365
Init = -1 ,
366
366
Update,
367
- ConsumeRawData,
368
- ExtractRawData
367
+ ConsumeRawData
368
+ };
369
+
370
+ enum class EUpdateResult : i8 {
371
+ Yield = -1 ,
372
+ ExtractRawData,
373
+ None
369
374
};
370
375
TSpillingSupportState (
371
376
TMemoryUsageInfo* memInfo,
@@ -398,28 +403,28 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
398
403
bool IsProcessingRequired () const {
399
404
if (InputStatus != EFetchResult::Finish) return true ;
400
405
401
- return HasRawDataToExtract || HasDataForProcessing ;
406
+ return !SpilledBuckets. empty () && SpilledBuckets. front (). BucketState != TSpilledBucket::EBucketState::InMemory ;
402
407
}
403
408
404
- bool UpdateAndWait () {
409
+ EUpdateResult Update () {
405
410
switch (GetMode ()) {
406
411
case EOperatingMode::InMemory: {
407
412
if (CheckMemoryAndSwitchToSpilling ()) {
408
- return UpdateAndWait ();
413
+ return Update ();
409
414
}
410
- return false ;
415
+ return EUpdateResult::None ;
411
416
}
412
417
413
418
case EOperatingMode::ProcessSpilled:
414
419
return ProcessSpilledDataAndWait ();
415
420
case EOperatingMode::Spilling: {
416
421
UpdateSpillingBuckets ();
417
422
418
- if (!HasMemoryForProcessing () && InputStatus != EFetchResult::Finish && TryToReduceMemoryAndWait ()) return true ;
423
+ if (!HasMemoryForProcessing () && InputStatus != EFetchResult::Finish && TryToReduceMemoryAndWait ()) return EUpdateResult::Yield ;
419
424
420
425
if (BufferForUsedInputItems.size ()) {
421
426
auto & bucket = SpilledBuckets[BufferForUsedInputItemsBucketId];
422
- if (bucket.AsyncWriteOperation .has_value ()) return true ;
427
+ if (bucket.AsyncWriteOperation .has_value ()) return EUpdateResult::Yield ;
423
428
424
429
bucket.AsyncWriteOperation = bucket.SpilledData ->WriteWideItem (BufferForUsedInputItems);
425
430
BufferForUsedInputItems.resize (0 ); // for freeing allocated key value asap
@@ -429,7 +434,7 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
429
434
430
435
// Prepare buffer for reading new key
431
436
BufferForKeyAndState.resize (KeyWidth);
432
- return false ;
437
+ return EUpdateResult::None ;
433
438
}
434
439
}
435
440
}
@@ -442,14 +447,6 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
442
447
return isNew ? ETasteResult::Init : ETasteResult::Update;
443
448
}
444
449
if (GetMode () == EOperatingMode::ProcessSpilled) {
445
- if (HasRawDataToExtract) {
446
- // Tongue not used here.
447
- Throat = BufferForUsedInputItems.data ();
448
- HasRawDataToExtract = false ;
449
- HasDataForProcessing = true ;
450
- return ETasteResult::ExtractRawData;
451
- }
452
- HasDataForProcessing = false ;
453
450
// while restoration we process buckets one by one starting from the first in a queue
454
451
bool isNew = SpilledBuckets.front ().InMemoryProcessingState ->TasteIt ();
455
452
Throat = SpilledBuckets.front ().InMemoryProcessingState ->Throat ;
@@ -476,8 +473,9 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
476
473
MKQL_ENSURE (BufferForUsedInputItems.size () == 0 , " Internal logic error" );
477
474
BufferForUsedInputItems.resize (ItemNodesSize);
478
475
BufferForUsedInputItemsBucketId = bucketId;
476
+
479
477
Throat = BufferForUsedInputItems.data ();
480
-
478
+
481
479
return ETasteResult::ConsumeRawData;
482
480
}
483
481
@@ -503,7 +501,7 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
503
501
BufferForKeyAndState.resize (0 );
504
502
}
505
503
506
- bool FlushSpillingBuffersAndWait () {
504
+ EUpdateResult FlushSpillingBuffersAndWait () {
507
505
UpdateSpillingBuckets ();
508
506
509
507
ui64 finishedCount = 0 ;
@@ -519,7 +517,7 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
519
517
}
520
518
}
521
519
522
- if (finishedCount != SpilledBuckets.size ()) return true ;
520
+ if (finishedCount != SpilledBuckets.size ()) return EUpdateResult::Yield ;
523
521
524
522
SwitchMode (EOperatingMode::ProcessSpilled);
525
523
@@ -628,11 +626,11 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
628
626
return false ;
629
627
}
630
628
631
- bool ProcessSpilledDataAndWait () {
632
- if (SpilledBuckets.empty ()) return false ;
629
+ EUpdateResult ProcessSpilledDataAndWait () {
630
+ if (SpilledBuckets.empty ()) return EUpdateResult::None ;
633
631
634
632
if (AsyncReadOperation) {
635
- if (!AsyncReadOperation->HasValue ()) return true ;
633
+ if (!AsyncReadOperation->HasValue ()) return EUpdateResult::Yield ;
636
634
if (RecoverState) {
637
635
SpilledBuckets[0 ].SpilledState ->AsyncReadCompleted (AsyncReadOperation->ExtractValue ().value (), Ctx.HolderFactory );
638
636
} else {
@@ -642,20 +640,16 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
642
640
}
643
641
644
642
auto & bucket = SpilledBuckets.front ();
645
- if (bucket.BucketState == TSpilledBucket::EBucketState::InMemory) return false ;
646
- if (HasDataForProcessing) {
647
- Tongue = bucket.InMemoryProcessingState ->Tongue ;
648
- Throat = bucket.InMemoryProcessingState ->Throat ;
649
- return false ;
650
- }
643
+ if (bucket.BucketState == TSpilledBucket::EBucketState::InMemory) return EUpdateResult::None;
644
+
651
645
// recover spilled state
652
646
while (!bucket.SpilledState ->Empty ()) {
653
647
RecoverState = true ;
654
648
BufferForKeyAndState.resize (KeyAndStateType->GetElementsCount ());
655
649
AsyncReadOperation = bucket.SpilledState ->ExtractWideItem (BufferForKeyAndState);
656
650
if (AsyncReadOperation) {
657
651
BufferForKeyAndState.resize (0 );
658
- return true ;
652
+ return EUpdateResult::Yield ;
659
653
}
660
654
for (size_t i = 0 ; i< KeyWidth; ++i) {
661
655
// jumping into unsafe world, refusing ownership
@@ -675,18 +669,16 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
675
669
BufferForUsedInputItems.resize (UsedInputItemType->GetElementsCount ());
676
670
AsyncReadOperation = bucket.SpilledData ->ExtractWideItem (BufferForUsedInputItems);
677
671
if (AsyncReadOperation) {
678
- return true ;
672
+ return EUpdateResult::Yield ;
679
673
}
680
674
675
+ Throat = BufferForUsedInputItems.data ();
681
676
Tongue = bucket.InMemoryProcessingState ->Tongue ;
682
- Throat = bucket.InMemoryProcessingState ->Throat ;
683
677
684
- HasRawDataToExtract = true ;
685
- return false ;
678
+ return EUpdateResult::ExtractRawData;
686
679
}
687
680
bucket.BucketState = TSpilledBucket::EBucketState::InMemory;
688
- HasDataForProcessing = false ;
689
- return false ;
681
+ return EUpdateResult::None;
690
682
}
691
683
692
684
EOperatingMode GetMode () const {
@@ -744,10 +736,6 @@ class TSpillingSupportState : public TComputationValue<TSpillingSupportState> {
744
736
private:
745
737
ui64 NextBucketToSpill = 0 ;
746
738
747
- bool HasDataForProcessing = false ;
748
-
749
- bool HasRawDataToExtract = false ;
750
-
751
739
TState InMemoryProcessingState;
752
740
const TMultiType* const UsedInputItemType;
753
741
const TMultiType* const KeyAndStateType;
@@ -1259,6 +1247,7 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode<TWideLastCombinerWra
1259
1247
, AllowSpilling(allowSpilling)
1260
1248
{}
1261
1249
1250
+ // MARK: DoCalculate
1262
1251
EFetchResult DoCalculate (NUdf::TUnboxedValue& state, TComputationContext& ctx, NUdf::TUnboxedValue*const * output) const {
1263
1252
if (!state.HasValue ()) {
1264
1253
MakeState (ctx, state);
@@ -1268,8 +1257,14 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode<TWideLastCombinerWra
1268
1257
auto **fields = ctx.WideFields .data () + WideFieldsIndex;
1269
1258
1270
1259
while (true ) {
1271
- if (ptr->UpdateAndWait ()) {
1272
- return EFetchResult::Yield;
1260
+ switch (ptr->Update ()) {
1261
+ case TSpillingSupportState::EUpdateResult::Yield:
1262
+ return EFetchResult::Yield;
1263
+ case TSpillingSupportState::EUpdateResult::ExtractRawData:
1264
+ Nodes.ExtractValues (ctx, static_cast <NUdf::TUnboxedValue*>(ptr->Throat ), fields);
1265
+ break ;
1266
+ case TSpillingSupportState::EUpdateResult::None:
1267
+ break ;
1273
1268
}
1274
1269
if (ptr->InputStatus != EFetchResult::Finish) {
1275
1270
for (auto i = 0U ; i < Nodes.ItemNodes .size (); ++i)
@@ -1297,9 +1292,6 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode<TWideLastCombinerWra
1297
1292
case TSpillingSupportState::ETasteResult::ConsumeRawData:
1298
1293
Nodes.ExtractValues (ctx, fields, static_cast <NUdf::TUnboxedValue*>(ptr->Throat ));
1299
1294
break ;
1300
- case TSpillingSupportState::ETasteResult::ExtractRawData:
1301
- Nodes.ExtractValues (ctx, static_cast <NUdf::TUnboxedValue*>(ptr->Throat ), fields);
1302
- break ;
1303
1295
}
1304
1296
continue ;
1305
1297
}
@@ -1366,13 +1358,18 @@ using TBaseComputation = TStatefulWideFlowCodegeneratorNode<TWideLastCombinerWra
1366
1358
1367
1359
block = more;
1368
1360
1369
- const auto waitMoreFunc = ConstantInt::get (Type::getInt64Ty (context), GetMethodPtr (&TSpillingSupportState::UpdateAndWait));
1370
- const auto waitMoreFuncPtr = CastInst::Create (Instruction::IntToPtr, waitMoreFunc, PointerType::getUnqual (boolFuncType), " wait_more_func" , block);
1371
- const auto waitMore = CallInst::Create (boolFuncType, waitMoreFuncPtr, { stateArg }, " wait_more" , block);
1361
+ const auto updateFunc = ConstantInt::get (Type::getInt64Ty (context), GetMethodPtr (&TSpillingSupportState::Update));
1362
+ const auto updateType = FunctionType::get (wayType, {stateArg->getType ()}, false );
1363
+ const auto updateFuncPtr = CastInst::Create (Instruction::IntToPtr, updateFunc, PointerType::getUnqual (updateType), " update_func" , block);
1364
+ const auto update = CallInst::Create (updateType, updateFuncPtr, { stateArg }, " update" , block);
1372
1365
1373
1366
result->addIncoming (ConstantInt::get (statusType, static_cast <i32 >(EFetchResult::Yield)), block);
1374
1367
1375
- BranchInst::Create (over, test, waitMore, block);
1368
+ const auto updateWay = SwitchInst::Create (update, test, 3U , block);
1369
+ updateWay->addCase (ConstantInt::get (wayType, static_cast <i8 >(TSpillingSupportState::EUpdateResult::Yield)), over);
1370
+ // TODO add exctraction code and jmp there
1371
+ updateWay->addCase (ConstantInt::get (wayType, static_cast <i8 >(TSpillingSupportState::EUpdateResult::ExtractRawData)), test);
1372
+ updateWay->addCase (ConstantInt::get (wayType, static_cast <i8 >(TSpillingSupportState::EUpdateResult::None)), test);
1376
1373
1377
1374
block = test;
1378
1375
0 commit comments