@@ -236,15 +236,20 @@ TEST(RefCountedVec, EraseBeginEnd) {
236236}
237237
238238struct NoDefaultCtor {
239- explicit NoDefaultCtor (int /* x */ ) {}
239+ explicit NoDefaultCtor (int ) {}
240240};
241241struct NoCopy {
242242 NoCopy () {}
243- NoCopy (const NoCopy& /* x */ ) = delete ;
243+ NoCopy (const NoCopy&) = delete ;
244244};
245245struct NoAssign {
246246 NoAssign () {}
247- NoAssign& operator =(const NoAssign& /* x */ ) = delete ;
247+ NoAssign& operator =(const NoAssign&) = delete ;
248+ };
249+ struct MoveOnly {
250+ MoveOnly () {}
251+ MoveOnly (MoveOnly&&) = default ;
252+ MoveOnly& operator =(MoveOnly&&) = default ;
248253};
249254TEST (InlinedVectorTest, NoDefaultCtor) {
250255 tensorflow::gtl::InlinedVector<NoDefaultCtor, 1 > v (10 , NoDefaultCtor (2 ));
@@ -258,6 +263,12 @@ TEST(InlinedVectorTest, NoAssign) {
258263 tensorflow::gtl::InlinedVector<NoAssign, 1 > v (10 );
259264 (void )v;
260265}
266+ TEST (InlinedVectorTest, MoveOnly) {
267+ gtl::InlinedVector<MoveOnly, 2 > v;
268+ v.push_back (MoveOnly{});
269+ v.push_back (MoveOnly{});
270+ v.push_back (MoveOnly{});
271+ }
261272
262273TEST (IntVec, Insert) {
263274 for (int len = 0 ; len < 20 ; len++) {
@@ -432,7 +443,7 @@ static std::vector<typename T::value_type> Vec(const T& src) {
432443TEST (IntVec, SelfRefPushBack) {
433444 std::vector<string> std_v;
434445 tensorflow::gtl::InlinedVector<string, 4 > v;
435- const string s = " A very long string to ensure heap." ;
446+ const string s = " A quite long string to ensure heap." ;
436447 std_v.push_back (s);
437448 v.push_back (s);
438449 for (int i = 0 ; i < 20 ; ++i) {
@@ -444,6 +455,21 @@ TEST(IntVec, SelfRefPushBack) {
444455 EXPECT_EQ (std_v, Vec (v));
445456}
446457
458+ TEST (IntVec, SelfRefPushBackWithMove) {
459+ std::vector<string> std_v;
460+ gtl::InlinedVector<string, 4 > v;
461+ const string s = " A quite long string to ensure heap." ;
462+ std_v.push_back (s);
463+ v.push_back (s);
464+ for (int i = 0 ; i < 20 ; ++i) {
465+ EXPECT_EQ (v.back (), std_v.back ());
466+
467+ v.push_back (std::move (v.back ()));
468+ std_v.push_back (std::move (std_v.back ()));
469+ }
470+ EXPECT_EQ (v.back (), std_v.back ());
471+ }
472+
447473TEST (IntVec, Swap) {
448474 for (int l1 = 0 ; l1 < 20 ; l1++) {
449475 SCOPED_TRACE (l1);
@@ -733,7 +759,7 @@ static void BM_InlinedVectorFill(int iters, int len) {
733759 v.push_back (j);
734760 }
735761 }
736- testing::BytesProcessed ((static_cast < int64>( iters) * len) * sizeof (int ));
762+ testing::BytesProcessed ((int64{ iters} * len) * sizeof (int ));
737763}
738764BENCHMARK (BM_InlinedVectorFill)->Range (0 , 1024 );
739765
@@ -745,7 +771,7 @@ static void BM_InlinedVectorFillRange(int iters, int len) {
745771 for (int i = 0 ; i < iters; i++) {
746772 IntVec TF_ATTRIBUTE_UNUSED v (ia.get (), ia.get () + len);
747773 }
748- testing::BytesProcessed ((static_cast < int64>( iters) * len) * sizeof (int ));
774+ testing::BytesProcessed ((int64{ iters} * len) * sizeof (int ));
749775}
750776BENCHMARK (BM_InlinedVectorFillRange)->Range (0 , 1024 );
751777
@@ -756,10 +782,46 @@ static void BM_StdVectorFill(int iters, int len) {
756782 v.push_back (j);
757783 }
758784 }
759- testing::BytesProcessed ((static_cast < int64>( iters) * len) * sizeof (int ));
785+ testing::BytesProcessed ((int64{ iters} * len) * sizeof (int ));
760786}
761787BENCHMARK (BM_StdVectorFill)->Range (0 , 1024 );
762788
789+ bool StringRepresentedInline (string s) {
790+ const char * chars = s.data ();
791+ string s1 = std::move (s);
792+ return s1.data () != chars;
793+ }
794+
795+ static void BM_InlinedVectorFillString (int iters, int len) {
796+ string strings[4 ] = {" a quite long string" , " another long string" ,
797+ " 012345678901234567" , " to cause allocation" };
798+ for (int i = 0 ; i < iters; i++) {
799+ gtl::InlinedVector<string, 8 > v;
800+ for (int j = 0 ; j < len; j++) {
801+ v.push_back (strings[j & 3 ]);
802+ }
803+ }
804+ testing::ItemsProcessed (int64{iters} * len);
805+ }
806+ BENCHMARK (BM_InlinedVectorFillString)->Range (0 , 1024 );
807+
808+ static void BM_StdVectorFillString (int iters, int len) {
809+ string strings[4 ] = {" a quite long string" , " another long string" ,
810+ " 012345678901234567" , " to cause allocation" };
811+ for (int i = 0 ; i < iters; i++) {
812+ std::vector<string> v;
813+ for (int j = 0 ; j < len; j++) {
814+ v.push_back (strings[j & 3 ]);
815+ }
816+ }
817+ testing::ItemsProcessed (int64{iters} * len);
818+ // The purpose of the benchmark is to verify that inlined vector is
819+ // efficient when moving is more efficent than copying. To do so, we
820+ // use strings that are larger than the small string optimization.
821+ CHECK (!StringRepresentedInline (strings[0 ]));
822+ }
823+ BENCHMARK (BM_StdVectorFillString)->Range (0 , 1024 );
824+
763825namespace {
764826struct Buffer { // some arbitrary structure for benchmarking.
765827 char * base;
0 commit comments