@@ -179,6 +179,114 @@ Y_UNIT_TEST(Pack) {
179
179
180
180
}
181
181
182
+ Y_UNIT_TEST (Unpack) {
183
+
184
+ TScopedAlloc alloc (__LOCATION__);
185
+
186
+ TColumnDesc kc1, kc2, pc1, pc2;
187
+
188
+ kc1.Role = EColumnRole::Key;
189
+ kc1.DataSize = 8 ;
190
+
191
+ kc2.Role = EColumnRole::Key;
192
+ kc2.DataSize = 4 ;
193
+
194
+ pc1.Role = EColumnRole::Payload;
195
+ pc1.DataSize = 8 ;
196
+
197
+ pc2.Role = EColumnRole::Payload;
198
+ pc2.DataSize = 4 ;
199
+
200
+ std::vector<TColumnDesc> columns{kc1, kc2, pc1, pc2};
201
+
202
+ auto tl = TTupleLayout::Create (columns);
203
+ UNIT_ASSERT (tl->TotalRowSize == 29 );
204
+
205
+ const ui64 NTuples1 = 10e6 ;
206
+
207
+ const ui64 Tuples1DataBytes = (tl->TotalRowSize ) * NTuples1;
208
+
209
+ std::vector<ui64> col1 (NTuples1, 0 );
210
+ std::vector<ui32> col2 (NTuples1, 0 );
211
+ std::vector<ui64> col3 (NTuples1, 0 );
212
+ std::vector<ui32> col4 (NTuples1, 0 );
213
+
214
+ std::vector<ui8> res (Tuples1DataBytes + 64 , 0 );
215
+
216
+ for (ui32 i = 0 ; i < NTuples1; ++i) {
217
+ col1[i] = i;
218
+ col2[i] = i;
219
+ col3[i] = i;
220
+ col4[i] = i;
221
+ }
222
+
223
+ const ui8* cols[4 ];
224
+
225
+ cols[0 ] = (ui8*) col1.data ();
226
+ cols[1 ] = (ui8*) col2.data ();
227
+ cols[2 ] = (ui8*) col3.data ();
228
+ cols[3 ] = (ui8*) col4.data ();
229
+
230
+ std::vector<ui8> colValid1 ((NTuples1 + 7 )/8 , ~0 );
231
+ std::vector<ui8> colValid2 ((NTuples1 + 7 )/8 , ~0 );
232
+ std::vector<ui8> colValid3 ((NTuples1 + 7 )/8 , ~0 );
233
+ std::vector<ui8> colValid4 ((NTuples1 + 7 )/8 , ~0 );
234
+ const ui8 *colsValid[4 ] = {
235
+ colValid1.data (),
236
+ colValid2.data (),
237
+ colValid3.data (),
238
+ colValid4.data (),
239
+ };
240
+
241
+ std::vector<ui8, TMKQLAllocator<ui8>> overflow;
242
+ tl->Pack (cols, colsValid, res.data (), overflow, 0 , NTuples1);
243
+
244
+ std::vector<ui64> col1_new (NTuples1, 0 );
245
+ std::vector<ui32> col2_new (NTuples1, 0 );
246
+ std::vector<ui64> col3_new (NTuples1, 0 );
247
+ std::vector<ui32> col4_new (NTuples1, 0 );
248
+
249
+ ui8* cols_new[4 ];
250
+ cols_new[0 ] = (ui8*) col1_new.data ();
251
+ cols_new[1 ] = (ui8*) col2_new.data ();
252
+ cols_new[2 ] = (ui8*) col3_new.data ();
253
+ cols_new[3 ] = (ui8*) col4_new.data ();
254
+
255
+ std::vector<ui8> colValid1_new ((NTuples1 + 7 )/8 , 0 );
256
+ std::vector<ui8> colValid2_new ((NTuples1 + 7 )/8 , 0 );
257
+ std::vector<ui8> colValid3_new ((NTuples1 + 7 )/8 , 0 );
258
+ std::vector<ui8> colValid4_new ((NTuples1 + 7 )/8 , 0 );
259
+
260
+ ui8 *colsValid_new[4 ] = {
261
+ colValid1_new.data (),
262
+ colValid2_new.data (),
263
+ colValid3_new.data (),
264
+ colValid4_new.data (),
265
+ };
266
+
267
+ std::chrono::steady_clock::time_point begin02 = std::chrono::steady_clock::now ();
268
+ tl->Unpack (cols_new, colsValid_new, res.data (), overflow, 0 , NTuples1);
269
+ std::chrono::steady_clock::time_point end02 = std::chrono::steady_clock::now ();
270
+ ui64 microseconds = std::chrono::duration_cast<std::chrono::microseconds>(end02 - begin02).count ();
271
+
272
+ if (microseconds == 0 ) microseconds = 1 ;
273
+
274
+ CTEST << " Time for " << (NTuples1) << " transpose (external cycle)= " << microseconds << " [microseconds]" << Endl;
275
+ CTEST << " Data size = " << Tuples1DataBytes / (1024 * 1024 ) << " [MB]" << Endl;
276
+ CTEST << " Calculating speed = " << Tuples1DataBytes / microseconds << " MB/sec" << Endl;
277
+ CTEST << Endl;
278
+
279
+ UNIT_ASSERT (std::memcmp (col1.data (), col1_new.data (), sizeof (ui64) * col1.size ()) == 0 );
280
+ UNIT_ASSERT (std::memcmp (col2.data (), col2_new.data (), sizeof (ui32) * col2.size ()) == 0 );
281
+ UNIT_ASSERT (std::memcmp (col3.data (), col3_new.data (), sizeof (ui64) * col3.size ()) == 0 );
282
+ UNIT_ASSERT (std::memcmp (col4.data (), col4_new.data (), sizeof (ui32) * col4.size ()) == 0 );
283
+
284
+ UNIT_ASSERT (std::memcmp (colValid1.data (), colValid1_new.data (), colValid1.size ()) == 0 );
285
+ UNIT_ASSERT (std::memcmp (colValid2.data (), colValid2_new.data (), colValid2.size ()) == 0 );
286
+ UNIT_ASSERT (std::memcmp (colValid3.data (), colValid3_new.data (), colValid3.size ()) == 0 );
287
+ UNIT_ASSERT (std::memcmp (colValid4.data (), colValid4_new.data (), colValid4.size ()) == 0 );
288
+ }
289
+
182
290
Y_UNIT_TEST (PackVarSize) {
183
291
184
292
TScopedAlloc alloc (__LOCATION__);
@@ -349,6 +457,197 @@ Y_UNIT_TEST(PackVarSize) {
349
457
UNIT_ASSERT_VALUES_EQUAL (expected_overflow[i], overflow[i]);
350
458
}
351
459
460
+ Y_UNIT_TEST (UnpackVarSize) {
461
+
462
+ TScopedAlloc alloc (__LOCATION__);
463
+
464
+ TColumnDesc kc1, kcv1, kcv2, kc2, pc1, pc2;
465
+
466
+ kc1.Role = EColumnRole::Key;
467
+ kc1.DataSize = 8 ;
468
+
469
+ kc2.Role = EColumnRole::Key;
470
+ kc2.DataSize = 4 ;
471
+
472
+ pc1.Role = EColumnRole::Payload;
473
+ pc1.DataSize = 8 ;
474
+
475
+ pc2.Role = EColumnRole::Payload;
476
+ pc2.DataSize = 4 ;
477
+
478
+ kcv1.Role = EColumnRole::Key;
479
+ kcv1.DataSize = 8 ;
480
+ kcv1.SizeType = EColumnSizeType::Variable;
481
+
482
+ kcv2.Role = EColumnRole::Key;
483
+ kcv2.DataSize = 16 ;
484
+ kcv2.SizeType = EColumnSizeType::Variable;
485
+
486
+ pc1.Role = EColumnRole::Payload;
487
+ pc1.DataSize = 8 ;
488
+
489
+ pc2.Role = EColumnRole::Payload;
490
+ pc2.DataSize = 4 ;
491
+
492
+ std::vector<TColumnDesc> columns{kc1, kc2, kcv1, kcv2, pc1, pc2};
493
+
494
+ auto tl = TTupleLayout::Create (columns);
495
+ CTEST << " TotalRowSize = " << tl->TotalRowSize << Endl;
496
+ UNIT_ASSERT_VALUES_EQUAL (tl->TotalRowSize , 54 );
497
+
498
+ const ui64 NTuples1 = 3 ;
499
+
500
+ const ui64 Tuples1DataBytes = (tl->TotalRowSize ) * NTuples1;
501
+
502
+ std::vector<ui64> col1 (NTuples1, 0 );
503
+ std::vector<ui32> col2 (NTuples1, 0 );
504
+ std::vector<ui64> col3 (NTuples1, 0 );
505
+ std::vector<ui32> col4 (NTuples1, 0 );
506
+
507
+ std::vector<ui32> vcol1 (1 , 0 );
508
+ std::vector<ui8> vcol1data;
509
+ std::vector<ui32> vcol2 (1 , 0 );
510
+ std::vector<ui8> vcol2data;
511
+
512
+ std::vector<ui8> res (Tuples1DataBytes + 64 , 0 );
513
+ std::vector<TString> vcol1str {
514
+ " abc" ,
515
+ " ABCDEFGHIJKLMNO" ,
516
+ " ZYXWVUTSPR"
517
+ };
518
+ std::vector<TString> vcol2str {
519
+ " ABC" ,
520
+ " abcdefghijklmno" ,
521
+ " zyxwvutspr"
522
+ };
523
+ for (auto &&str: vcol1str) {
524
+ for (auto c: str)
525
+ vcol1data.push_back (c);
526
+ vcol1.push_back (vcol1data.size ());
527
+ }
528
+ UNIT_ASSERT_VALUES_EQUAL (vcol1.size (), NTuples1 + 1 );
529
+ for (auto &&str: vcol2str) {
530
+ for (auto c: str)
531
+ vcol2data.push_back (c);
532
+ vcol2.push_back (vcol2data.size ());
533
+ }
534
+ UNIT_ASSERT_VALUES_EQUAL (vcol2.size (), NTuples1 + 1 );
535
+ for (ui32 i = 0 ; i < NTuples1; ++i) {
536
+ col1[i] = (1ull <<(sizeof (col1[0 ])*8 - 4 )) + i + 1 ;
537
+ col2[i] = (2ull <<(sizeof (col2[0 ])*8 - 4 )) + i + 1 ;
538
+ col3[i] = (3ull <<(sizeof (col3[0 ])*8 - 4 )) + i + 1 ;
539
+ col4[i] = (4ull <<(sizeof (col4[0 ])*8 - 4 )) + i + 1 ;
540
+ }
541
+
542
+ const ui8* cols[4 + 2 *2 ];
543
+
544
+ cols[0 ] = (ui8*) col1.data ();
545
+ cols[1 ] = (ui8*) col2.data ();
546
+ cols[2 ] = (ui8*) vcol1.data ();
547
+ cols[3 ] = (ui8*) vcol1data.data ();
548
+ cols[4 ] = (ui8*) vcol2.data ();
549
+ cols[5 ] = (ui8*) vcol2data.data ();
550
+ cols[6 ] = (ui8*) col3.data ();
551
+ cols[7 ] = (ui8*) col4.data ();
552
+
553
+ std::vector<ui8, TMKQLAllocator<ui8>> overflow;
554
+ std::vector<ui8> colValid ((NTuples1 + 7 )/8 , ~0 );
555
+ const ui8 *colsValid[8 ] = {
556
+ colValid.data (),
557
+ colValid.data (),
558
+ colValid.data (),
559
+ nullptr ,
560
+ colValid.data (),
561
+ nullptr ,
562
+ colValid.data (),
563
+ colValid.data (),
564
+ };
565
+
566
+ tl->Pack (cols, colsValid, res.data (), overflow, 0 , NTuples1);
567
+
568
+ std::vector<ui64> col1_new (NTuples1, 0 );
569
+ std::vector<ui32> col2_new (NTuples1, 0 );
570
+ std::vector<ui64> col3_new (NTuples1, 0 );
571
+ std::vector<ui32> col4_new (NTuples1, 0 );
572
+
573
+ std::vector<ui32> vcol1_new (NTuples1 + 1 , 0 );
574
+ std::vector<ui8> vcol1data_new (vcol1data.size ());
575
+ std::vector<ui32> vcol2_new (NTuples1 + 1 , 0 );
576
+ std::vector<ui8> vcol2data_new (vcol2data.size ());
577
+
578
+ ui8* cols_new[4 + 2 * 2 ];
579
+ cols_new[0 ] = (ui8*) col1_new.data ();
580
+ cols_new[1 ] = (ui8*) col2_new.data ();
581
+ cols_new[2 ] = (ui8*) vcol1_new.data ();
582
+ cols_new[3 ] = (ui8*) vcol1data_new.data ();
583
+ cols_new[4 ] = (ui8*) vcol2_new.data ();
584
+ cols_new[5 ] = (ui8*) vcol2data_new.data ();
585
+ cols_new[6 ] = (ui8*) col3_new.data ();
586
+ cols_new[7 ] = (ui8*) col4_new.data ();
587
+
588
+ std::vector<ui8> colValid1_new ((NTuples1 + 7 )/8 , 0 );
589
+ colValid1_new.back () = ~0 ;
590
+ std::vector<ui8> colValid2_new ((NTuples1 + 7 )/8 , 0 );
591
+ colValid2_new.back () = ~0 ;
592
+ std::vector<ui8> colValid3_new ((NTuples1 + 7 )/8 , 0 );
593
+ colValid3_new.back () = ~0 ;
594
+ std::vector<ui8> colValid4_new ((NTuples1 + 7 )/8 , 0 );
595
+ colValid4_new.back () = ~0 ;
596
+ std::vector<ui8> colValid5_new ((NTuples1 + 7 )/8 , 0 );
597
+ colValid5_new.back () = ~0 ;
598
+ std::vector<ui8> colValid6_new ((NTuples1 + 7 )/8 , 0 );
599
+ colValid6_new.back () = ~0 ;
600
+
601
+ ui8 *colsValid_new[8 ] = {
602
+ colValid1_new.data (),
603
+ colValid2_new.data (),
604
+ colValid3_new.data (),
605
+ nullptr ,
606
+ colValid4_new.data (),
607
+ nullptr ,
608
+ colValid5_new.data (),
609
+ colValid6_new.data (),
610
+ };
611
+
612
+ std::chrono::steady_clock::time_point begin02 = std::chrono::steady_clock::now ();
613
+ tl->Unpack (cols_new, colsValid_new, res.data (), overflow, 0 , NTuples1);
614
+ std::chrono::steady_clock::time_point end02 = std::chrono::steady_clock::now ();
615
+ ui64 microseconds = std::chrono::duration_cast<std::chrono::microseconds>(end02 - begin02).count ();
616
+
617
+ if (microseconds == 0 )
618
+ microseconds = 1 ;
619
+
620
+ CTEST << " Time for " << (NTuples1) << " transpose (external cycle)= " << microseconds << " [microseconds]" << Endl;
621
+ #ifndef NDEBUG
622
+ CTEST << " Result size = " << Tuples1DataBytes << Endl;
623
+ CTEST << " Result = " ;
624
+ for (ui32 i = 0 ; i < Tuples1DataBytes; ++i)
625
+ CTEST << int (res[i]) << ' ' ;
626
+ CTEST << Endl;
627
+ CTEST << " Overflow size = " << overflow.size () << Endl;
628
+ CTEST << " Overflow = " ;
629
+ for (auto c: overflow)
630
+ CTEST << int (c) << ' ' ;
631
+ CTEST << Endl;
632
+ #endif
633
+
634
+ UNIT_ASSERT (std::memcmp (cols[0 ], cols_new[0 ], sizeof (ui64) * col1.size ()) == 0 );
635
+ UNIT_ASSERT (std::memcmp (cols[1 ], cols_new[1 ], sizeof (ui32) * col2.size ()) == 0 );
636
+ UNIT_ASSERT (std::memcmp (cols[2 ], cols_new[2 ], sizeof (ui32) * vcol1.size ()) == 0 );
637
+ UNIT_ASSERT (std::memcmp (cols[3 ], cols_new[3 ], vcol1data.size ()) == 0 );
638
+ UNIT_ASSERT (std::memcmp (cols[4 ], cols_new[4 ], sizeof (ui32) * vcol2.size ()) == 0 );
639
+ UNIT_ASSERT (std::memcmp (cols[5 ], cols_new[5 ], vcol1data.size ()) == 0 );
640
+ UNIT_ASSERT (std::memcmp (cols[6 ], cols_new[6 ], sizeof (ui64) * col3.size ()) == 0 );
641
+ UNIT_ASSERT (std::memcmp (cols[7 ], cols_new[7 ], sizeof (ui32) * col4.size ()) == 0 );
642
+
643
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid1_new.data (), colValid.size ()) == 0 );
644
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid2_new.data (), colValid.size ()) == 0 );
645
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid3_new.data (), colValid.size ()) == 0 );
646
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid4_new.data (), colValid.size ()) == 0 );
647
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid5_new.data (), colValid.size ()) == 0 );
648
+ UNIT_ASSERT (std::memcmp (colValid.data (), colValid6_new.data (), colValid.size ()) == 0 );
649
+ }
650
+
352
651
Y_UNIT_TEST (PackVarSizeBig) {
353
652
354
653
TScopedAlloc alloc (__LOCATION__);
0 commit comments