mem_io.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #pragma once
  2. #include "bin_saver.h"
  3. namespace NMemIoInternals {
  4. class TMemoryStream: public IBinaryStream {
  5. TVector<char>& Data;
  6. ui64 Pos;
  7. public:
  8. TMemoryStream(TVector<char>* data, ui64 pos = 0)
  9. : Data(*data)
  10. , Pos(pos)
  11. {
  12. }
  13. ~TMemoryStream() override {
  14. } // keep gcc happy
  15. bool IsValid() const override {
  16. return true;
  17. }
  18. bool IsFailed() const override {
  19. return false;
  20. }
  21. private:
  22. int WriteImpl(const void* userBuffer, int size) override {
  23. if (size == 0)
  24. return 0;
  25. Y_ASSERT(size > 0);
  26. if (Pos + size > Data.size())
  27. Data.yresize(Pos + size);
  28. memcpy(&Data[Pos], userBuffer, size);
  29. Pos += size;
  30. return size;
  31. }
  32. int ReadImpl(void* userBuffer, int size) override {
  33. if (size == 0)
  34. return 0;
  35. Y_ASSERT(size > 0);
  36. int res = Min(Data.size() - Pos, (ui64)size);
  37. if (res)
  38. memcpy(userBuffer, &Data[Pos], res);
  39. Pos += res;
  40. return res;
  41. }
  42. };
  43. template <class T>
  44. inline void SerializeMem(bool bRead, TVector<char>* data, T& c, bool stableOutput = false) {
  45. if (IBinSaver::HasNonTrivialSerializer<T>(0u)) {
  46. TMemoryStream f(data);
  47. {
  48. IBinSaver bs(f, bRead, stableOutput);
  49. bs.Add(1, &c);
  50. }
  51. } else {
  52. if (bRead) {
  53. Y_ASSERT(data->size() == sizeof(T));
  54. c = *reinterpret_cast<T*>(&(*data)[0]);
  55. } else {
  56. data->yresize(sizeof(T));
  57. *reinterpret_cast<T*>(&(*data)[0]) = c;
  58. }
  59. }
  60. }
  61. ////////////////////////////////////////////////////////////////////////////
  62. class THugeMemoryStream: public IBinaryStream {
  63. TVector<TVector<char>>& Data;
  64. i64 Block, Pos;
  65. bool ShrinkOnRead;
  66. enum {
  67. MAX_BLOCK_SIZE = 1024 * 1024 // Aligned with cache size
  68. };
  69. public:
  70. THugeMemoryStream(TVector<TVector<char>>* data, bool shrinkOnRead = false)
  71. : Data(*data)
  72. , Block(0)
  73. , Pos(0)
  74. , ShrinkOnRead(shrinkOnRead)
  75. {
  76. Y_ASSERT(!data->empty());
  77. }
  78. ~THugeMemoryStream() override {
  79. } // keep gcc happy
  80. bool IsValid() const override {
  81. return true;
  82. }
  83. bool IsFailed() const override {
  84. return false;
  85. }
  86. private:
  87. int WriteImpl(const void* userDataArg, int sizeArg) override {
  88. if (sizeArg == 0)
  89. return 0;
  90. const char* userData = (const char*)userDataArg;
  91. i64 size = sizeArg;
  92. i64 newSize = Pos + size;
  93. if (newSize > Data[Block].ysize()) {
  94. while (newSize > MAX_BLOCK_SIZE) {
  95. int maxWrite = MAX_BLOCK_SIZE - Pos;
  96. Data[Block].yresize(MAX_BLOCK_SIZE);
  97. if (maxWrite) {
  98. memcpy(&Data[Block][Pos], userData, maxWrite);
  99. userData += maxWrite;
  100. size -= maxWrite;
  101. }
  102. ++Block;
  103. Pos = 0;
  104. Data.resize(Block + 1);
  105. newSize = Pos + size;
  106. }
  107. Data[Block].yresize(newSize);
  108. }
  109. if (size) {
  110. memcpy(&Data[Block][Pos], userData, size);
  111. }
  112. Pos += size;
  113. return sizeArg;
  114. }
  115. int ReadImpl(void* userDataArg, int sizeArg) override {
  116. if (sizeArg == 0)
  117. return 0;
  118. char* userData = (char*)userDataArg;
  119. i64 size = sizeArg;
  120. i64 rv = 0;
  121. while (size > 0) {
  122. int curBlockSize = Data[Block].ysize();
  123. int maxRead = 0;
  124. if (Pos + size > curBlockSize) {
  125. maxRead = curBlockSize - Pos;
  126. if (maxRead) {
  127. memcpy(userData, &Data[Block][Pos], maxRead);
  128. userData += maxRead;
  129. size -= maxRead;
  130. rv += maxRead;
  131. }
  132. if (Block + 1 == Data.ysize()) {
  133. memset(userData, 0, size);
  134. return rv;
  135. }
  136. if (ShrinkOnRead) {
  137. TVector<char>().swap(Data[Block]);
  138. }
  139. ++Block;
  140. Pos = 0;
  141. } else {
  142. memcpy(userData, &Data[Block][Pos], size);
  143. Pos += size;
  144. rv += size;
  145. return rv;
  146. }
  147. }
  148. return rv;
  149. }
  150. };
  151. template <class T>
  152. inline void SerializeMem(bool bRead, TVector<TVector<char>>* data, T& c, bool stableOutput = false) {
  153. if (data->empty()) {
  154. data->resize(1);
  155. }
  156. THugeMemoryStream f(data);
  157. {
  158. IBinSaver bs(f, bRead, stableOutput);
  159. bs.Add(1, &c);
  160. }
  161. }
  162. }
  163. template <class T>
  164. inline void SerializeMem(const TVector<char>& data, T& c) {
  165. if (IBinSaver::HasNonTrivialSerializer<T>(0u)) {
  166. TVector<char> tmp(data);
  167. SerializeFromMem(&tmp, c);
  168. } else {
  169. Y_ASSERT(data.size() == sizeof(T));
  170. c = *reinterpret_cast<const T*>(&data[0]);
  171. }
  172. }
  173. template <class T, class D>
  174. inline void SerializeToMem(D* data, T& c, bool stableOutput = false) {
  175. NMemIoInternals::SerializeMem(false, data, c, stableOutput);
  176. }
  177. template <class T, class D>
  178. inline void SerializeFromMem(D* data, T& c, bool stableOutput = false) {
  179. NMemIoInternals::SerializeMem(true, data, c, stableOutput);
  180. }
  181. // Frees memory in (*data)[i] immediately upon it's deserialization, thus keeps low overall memory consumption for data + object.
  182. template <class T>
  183. inline void SerializeFromMemShrinkInput(TVector<TVector<char>>* data, T& c) {
  184. if (data->empty()) {
  185. data->resize(1);
  186. }
  187. NMemIoInternals::THugeMemoryStream f(data, true);
  188. {
  189. IBinSaver bs(f, true, false);
  190. bs.Add(1, &c);
  191. }
  192. data->resize(0);
  193. data->shrink_to_fit();
  194. }