CPPFormatLibary提升效率的优化原理

CPPFormatLibary,以下简称FL,介绍:关于CPPFormatLibary

与stringstream,甚至C库的sprintf系列想比,FL在速度上都有优势,而且是在支持.net格式化风格的基础上。要实现这一点,需要多种优化结合在一起,有代码技巧方面的,也有设计策略上的。下面简要的对这些内容进行讲解:

1.  Pattern缓存

在C库函数sprintf中,比如这行代码:

1          char szBuf[64];
2          sprintf_s(szBuf, "%d--#--%8.2f--#--%s", 100, -40.2f, " String ");

格式化字符串"%d--#--%8.2f--#--%s"在每次函数调用的时候,都需要分析一次,依次找出对应的格式化符,在实际开发过程中,多数情况下,格式化字符串并没有任何不同,因此这个分析属于重复分析。因此在设计FL时将这样的格式化字符串称为PatternList,并使用Hash容器对这个PatternList进行存储,在每次格式化之前,首先在容器中查找对应字符串的Pattern是否已经存在,有的话则直接使用已经分析的结果。

下面的代码是Pattern的定义,PatternList则为对应的数组:

 1         /**
 2         * @brief This is the description of a Format unit
 3         * @example {0} {0:d}
 4         */
 5         template < typename TCharType >
 6         class TFormatPattern
 7         {
 8         public:
 9             typedef TCharType                                    CharType;
10             typedef unsigned char                                ByteType;
11             typedef std::size_t                                  SizeType;
12
13             enum EFormatFlag
14             {
15                 FF_Raw,
16                 FF_None,
17                 FF_Decimal,
18                 FF_Exponent,
19                 FF_FixedPoint,
20                 FF_General,
21                 FF_CSV,
22                 FF_Percentage,
23                 FF_Hex
24             };
25
26             enum EAlignFlag
27             {
28                 AF_Right,
29                 AF_Left
30             };
31
32             TFormatPattern() :
33                 Start((SizeType)-1),
34                 Len(0),
35                 Flag(FF_Raw),
36                 Align(AF_Right),
37                 Index((ByteType)-1),
38                 Precision((ByteType)-1),
39                 Width((ByteType)-1)
40
41             {
42             }
43
44             SizeType  GetLegnth() const
45             {
46                 return Len;
47             }
48
49             bool    IsValid() const
50             {
51                 return Start != -1 && Len != -1 && Index >= 0;
52             }
53
54             bool    HasWidth() const
55             {
56                 return Width != (ByteType)-1;
57             }
58
59             bool    HasPrecision() const
60             {
61                 return Precision != (ByteType)-1;
62             }
63
64         public:
65             SizeType      Start;
66             SizeType      Len;
67             EFormatFlag   Flag;
68             EAlignFlag    Align;
69
70             ByteType      Index;
71             ByteType      Precision;
72             ByteType      Width;
73         };

这个Pattern就代表了分析格式化字符串的每一个单元。

1         StandardLibrary::FormatTo(str, "{0}--#--{1,8}--#--{2}", 100, -40.2f, " String ");

在这行代码中,PatternList一共有5个Pattern,分别是:

    {0} 参数0

     --#-- 原始类型

    {1,8} 参数1 宽度8

    --#-- 原始类型 纯字符串

    {2} 参数2

这样设计可以优化掉重复的字符串Parse。

2.各种类型到字符串转换的算法优化

这部分代码完全存在于文件Algorithm.hpp中,这里面包含了诸如int、double等转换为字符串的快速算法,实测性能优于sprintf和atoi之类。通过这些基础算法的优化,性能可以得到相当不错的提升。

 1        template < typename TCharType >
 2         inline void StringReverse(TCharType* Start, TCharType* End)
 3         {
 4             TCharType Aux;
 5
 6             while (Start < End)
 7             {
 8                 Aux = *End;
 9                 *End-- = *Start;
10                 *Start++ = Aux;
11             }
12         }
13
14         namespace Detail
15         {
16             const char DigitMap[] =
17             {
18                 ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘,
19                 ‘7‘, ‘8‘, ‘9‘, ‘A‘, ‘B‘, ‘C‘, ‘D‘,
20                 ‘E‘, ‘F‘
21             };
22         }
23
24         template < typename TCharType >
25         inline SIZE_T Int64ToString(INT64 Value, TCharType* Buf, INT Base)
26         {
27             assert(Base > 0 && static_cast<SIZE_T>(Base) <= _countof(Detail::DigitMap));
28
29             TCharType* Str = Buf;
30
31             UINT64 UValue = (Value < 0) ? -Value : Value;
32
33             // Conversion. Number is reversed.
34             do
35             {
36                 *Str++ = Detail::DigitMap[UValue%Base];
37             } while (UValue /= Base);
38
39             if (Value < 0)
40             {
41                 *Str++ = ‘-‘;
42             }
43
44             *Str = ‘\0‘;
45
46             // Reverse string
47             StringReverse<TCharType>(Buf, Str - 1);
48
49             return Str - Buf;
50         }

上面这段代码展示的是快速整数到字符串的转换。据说基于sse指令的各种转换会更快,然而担心兼容性问题影响跨平台,我并未采用。

3. 栈容器和栈字符串

这部分代码存在于文件Utility.hpp中,这部分代码的优化原理就是在需要的动态内存并不大的时候,直接使用栈内存,当内存需求大到超过一定阀值的时候,自动申请堆内存并将栈数据转移到堆内存上。在大多数情况下,我们需要的内存都是很少,因此在绝大多数情况下,都能起到相当显著的优化效果。

  1         template <
  2             typename T,
  3             INT DefaultLength = 0xFF,
  4             INT ExtraLength = 0
  5         >
  6         class TAutoArray
  7         {
  8         public:
  9             typedef TAutoArray<T, DefaultLength, ExtraLength>   SelfType;
 10
 11             enum
 12             {
 13                 DEFAULT_LENGTH = DefaultLength
 14             };
 15
 16             class ConstIterator : Noncopyable
 17             {
 18             public:
 19                 ConstIterator(const SelfType& InRef) :
 20                     Ref(InRef),
 21                     Index( InRef.GetLength()>0?0:-1 )
 22                 {
 23                 }
 24
 25                 bool IsValid() const
 26                 {
 27                     return Index < Ref.GetLength();
 28                 }
 29
 30                 bool Next()
 31                 {
 32                     ++Index;
 33
 34                     return IsValid();
 35                 }
 36
 37                 const T& operator *() const
 38                 {
 39                     const T* Ptr = Ref.GetDataPtr();
 40
 41                     return Ptr[Index];
 42                 }
 43             private:
 44                 ConstIterator& operator = (const ConstIterator&);
 45                 ConstIterator(ConstIterator&);
 46             protected:
 47                 const SelfType&   Ref;
 48                 SIZE_T            Index;
 49             };
 50
 51             TAutoArray() :
 52                 Count(0),
 53                 AllocatedCount(0),
 54                 HeapValPtr(NULL)
 55             {
 56             }
 57
 58             ~TAutoArray()
 59             {
 60                 ReleaseHeapData();
 61
 62                 Count = 0;
 63             }
 64
 65             TAutoArray(const SelfType& Other) :
 66                 Count(Other.Count),
 67                 AllocatedCount(Other.AllocatedCount),
 68                 HeapValPtr(NULL)
 69             {
 70                 if (Count > 0)
 71                 {
 72                     if (Other.IsDataOnStack())
 73                     {
 74                         Algorithm::CopyArray(Other.StackVal, Other.StackVal + Count, StackVal);
 75                     }
 76                     else
 77                     {
 78                         HeapValPtr = Allocate(AllocatedCount);
 79                         Algorithm::CopyArray(Other.HeapValPtr, Other.HeapValPtr + Count, HeapValPtr);
 80                     }
 81                 }
 82             }
 83
 84             SelfType& operator = (const SelfType& Other)
 85             {
 86                 if (this == &Other)
 87                 {
 88                     return *this;
 89                 }
 90
 91                 ReleaseHeapData();
 92
 93                 Count = Other.Count;
 94                 AllocatedCount = Other.AllocatedCount;
 95                 HeapValPtr = NULL;
 96
 97                 if (Count > 0)
 98                 {
 99                     if (Other.IsDataOnStack())
100                     {
101                         Algorithm::CopyArray(Other.StackVal, Other.StackVal + Count, StackVal);
102                     }
103                     else
104                     {
105                         HeapValPtr = Allocate(AllocatedCount);
106                         Algorithm::CopyArray(Other.HeapValPtr, Other.HeapValPtr + Count, HeapValPtr);
107                     }
108                 }
109
110                 return *this;
111             }
112
113             SelfType& TakeFrom(SelfType& Other)
114             {
115                 if (this == &Other)
116                 {
117                     return *this;
118                 }
119
120                 Count = Other.Count;
121                 AllocatedCount = Other.AllocatedCount;
122                 HeapValPtr = Other.HeapValPtr;
123
124                 if (Count > 0 && Other.IsDataOnStack())
125                 {
126                     Algorithm::MoveArray(Other.StackVal, Other.StackVal + Count, StackVal);
127                 }
128
129                 Other.Count = 0;
130                 Other.AllocatedCount = 0;
131                 Other.HeapValPtr = NULL;
132             }
133
134             void TakeTo(SelfType& Other)
135             {
136                 Other.TakeFrom(*this);
137             }
138
139 #if FL_PLATFORM_HAS_RIGHT_VALUE_REFERENCE
140             TAutoArray( SelfType && Other ) :
141                 Count(Other.Count),
142                 AllocatedCount(Other.AllocatedCount),
143                 HeapValPtr(Other.HeapValPtr)
144             {
145                 if (Count > 0 && Other.IsDataOnStack())
146                 {
147                     Algorithm::MoveArray(Other.StackVal, Other.StackVal + Count, StackVal);
148                 }
149
150                 Other.Count = 0;
151                 Other.AllocatedCount = 0;
152                 Other.HeapValPtr = NULL;
153             }
154
155             SelfType& operator = (SelfType&& Other )
156             {
157                 return TakeFrom(Other);
158             }
159 #endif
160
161             bool  IsDataOnStack() const
162             {
163                 return HeapValPtr == NULL;
164             }
165
166             void  AddItem(const T& InValue)
167             {
168                 if (IsDataOnStack())
169                 {
170                     if (Count < DEFAULT_LENGTH)
171                     {
172                         StackVal[Count] = InValue;
173                         ++Count;
174                     }
175                     else if (Count == DEFAULT_LENGTH)
176                     {
177                         InitialMoveDataToHeap();
178
179                         assert(Count < AllocatedCount);
180
181                         HeapValPtr[Count] = InValue;
182                         ++Count;
183                     }
184                     else
185                     {
186                         assert(false && "internal error");
187                     }
188                 }
189                 else
190                 {
191                     if (Count < AllocatedCount)
192                     {
193                         HeapValPtr[Count] = InValue;
194                         ++Count;
195                     }
196                     else
197                     {
198                         ExpandHeapSpace();
199
200                         assert(Count < AllocatedCount);
201                         HeapValPtr[Count] = InValue;
202                         ++Count;
203                     }
204                 }
205             }
206
207             SIZE_T GetLength() const
208             {
209                 return Count;
210             }
211
212             SIZE_T GetAllocatedCount() const
213             {
214                 return AllocatedCount;
215             }
216
217             T* GetDataPtr()
218             {
219                 return IsDataOnStack() ? StackVal : HeapValPtr;
220             }
221
222             const T* GetDataPtr() const
223             {
224                 return IsDataOnStack() ? StackVal : HeapValPtr;
225             }
226
227             T* GetUnusedPtr()
228             {
229                 return IsDataOnStack() ? StackVal + Count : HeapValPtr + Count;
230             }
231
232             const T* GetUnusedPtr() const
233             {
234                 return IsDataOnStack() ? StackVal + Count : HeapValPtr + Count;
235             }
236
237             SIZE_T GetCapacity() const
238             {
239                 return IsDataOnStack() ?
240                     DEFAULT_LENGTH - Count :
241                     AllocatedCount - Count;
242             }
243
244             T& operator []( SIZE_T Index )
245             {
246                 assert( Index < GetLength() );
247
248                 return GetDataPtr()[Index];
249             }
250
251             const T& operator []( SIZE_T Index ) const
252             {
253                 assert( Index < GetLength() );
254
255                 return GetDataPtr()[Index];
256             }
257
258         protected:
259             void  InitialMoveDataToHeap()
260             {
261                 assert(HeapValPtr == NULL);
262
263                 AllocatedCount = DEFAULT_LENGTH * 2;
264
265                 HeapValPtr = Allocate(AllocatedCount);
266
267 #if FL_PLATFORM_HAS_RIGHT_VALUE_REFERENCE
268                 Algorithm::MoveArray(StackVal, StackVal + Count, HeapValPtr);
269 #else
270                 Algorithm::CopyArray(StackVal, StackVal + Count, HeapValPtr);
271 #endif
272             }
273
274             void  ExpandHeapSpace()
275             {
276                 SIZE_T NewCount = AllocatedCount * 2;
277                 assert(NewCount > AllocatedCount);
278
279                 T* DataPtr = Allocate(NewCount);
280
281                 assert(DataPtr);
282
283 #if FL_PLATFORM_HAS_RIGHT_VALUE_REFERENCE
284                 Algorithm::MoveArray(HeapValPtr, HeapValPtr + Count, DataPtr);
285 #else
286                 Algorithm::CopyArray(HeapValPtr, HeapValPtr + Count, DataPtr);
287 #endif
288                 ReleaseHeapData();
289
290                 HeapValPtr = DataPtr;
291                 AllocatedCount = NewCount;
292             }
293
294             void  ReleaseHeapData()
295             {
296                 if (HeapValPtr)
297                 {
298                     delete[] HeapValPtr;
299                     HeapValPtr = NULL;
300                 }
301
302                 AllocatedCount = 0;
303             }
304
305             static T*  Allocate(const SIZE_T InAllocatedCount)
306             {
307                 // +ExtraLength this is a hack method for saving string on it.
308                 return new T[InAllocatedCount + ExtraLength];
309             }
310
311         protected:
312             SIZE_T        Count;
313             SIZE_T        AllocatedCount;
314
315             // +ExtraLength this is a hack method for saving string on it.
316             T             StackVal[DEFAULT_LENGTH + ExtraLength];
317
318             T*            HeapValPtr;
319         };

上面这段代码展示的就是这个设想的实现。这是一个模板类,基于这个类实现了栈字符串。同时默认的PatternList也是使用这个模板来保存的,这样在节约了大量的内存分配操作之后,性能得到进一步的提升。

  1 // String Wrapper
  2         template < typename TCharType >
  3         class TAutoString :
  4             public TAutoArray< TCharType, 0xFF, 2 >
  5         {
  6         public:
  7             typedef TAutoArray< TCharType, 0xFF, 2 > Super;
  8             typedef Mpl::TCharTraits<TCharType>      CharTraits;
  9             typedef TCharType                        CharType;
 10
 11 #if !FL_COMPILER_MSVC
 12             using Super::Count;
 13             using Super::AllocatedCount;
 14             using Super::HeapValPtr;
 15             using Super::StackVal;
 16             using Super::Allocate;
 17             using Super::IsDataOnStack;
 18             using Super::DEFAULT_LENGTH;
 19             using Super::GetDataPtr;
 20             using Super::ReleaseHeapData;
 21 #endif
 22
 23             TAutoString()
 24             {
 25             }
 26
 27             TAutoString(const CharType* pszStr)
 28             {
 29                 if (pszStr)
 30                 {
 31                     const SIZE_T Length = CharTraits::length(pszStr);
 32
 33                     Count = Length;
 34
 35                     if (Length <= DEFAULT_LENGTH)
 36                     {
 37                         CharTraits::copy(pszStr, pszStr + Length, StackVal);
 38                         StackVal[Count] = 0;
 39                     }
 40                     else
 41                     {
 42                         HeapValPtr = Allocate(Length);
 43                         CharTraits::copy(pszStr, pszStr + Length, HeapValPtr);
 44                         HeapValPtr[Count] = 0;
 45                     }
 46                 }
 47             }
 48
 49             void  AddChar(CharType InValue)
 50             {
 51                 AddItem(InValue);
 52
 53                 if (IsDataOnStack())
 54                 {
 55                     StackVal[Count] = 0;
 56                 }
 57                 else
 58                 {
 59                     HeapValPtr[Count] = 0;
 60                 }
 61             }
 62
 63             void AddStr(const CharType* pszStart, const CharType* pszEnd = NULL)
 64             {
 65                 const SIZE_T Length = pszEnd ? pszEnd - pszStart : CharTraits::length(pszStart);
 66
 67                 if (IsDataOnStack())
 68                 {
 69                     if (Count + Length <= DEFAULT_LENGTH)
 70                     {
 71                         CharTraits::copy(StackVal+Count, pszStart, Length);
 72                         Count += Length;
 73
 74                         StackVal[Count] = 0;
 75                     }
 76                     else
 77                     {
 78                         assert(!HeapValPtr);
 79
 80                         AllocatedCount = static_cast<SIZE_T>((Count + Length)*1.5f);
 81                         HeapValPtr = Allocate(AllocatedCount);
 82                         assert(HeapValPtr);
 83
 84                         if (Count > 0)
 85                         {
 86                             CharTraits::copy(HeapValPtr, StackVal, Count);
 87                         }
 88
 89                         CharTraits::copy(HeapValPtr+Count, pszStart, Length);
 90
 91                         Count += Length;
 92
 93                         HeapValPtr[Count] = 0;
 94                     }
 95                 }
 96                 else
 97                 {
 98                     if (Count + Length <= AllocatedCount)
 99                     {
100                         CharTraits::copy(HeapValPtr+Count, pszStart, Length);
101                         Count += Length;
102
103                         HeapValPtr[Count] = 0;
104                     }
105                     else
106                     {
107                         SIZE_T NewCount = static_cast<SIZE_T>((Count + Length)*1.5f);
108
109                         CharType* DataPtr = Allocate(NewCount);
110
111                         if (Count > 0)
112                         {
113                             CharTraits::copy(DataPtr, HeapValPtr, Count);
114                         }
115
116                         ReleaseHeapData();
117
118                         CharTraits::copy(DataPtr, pszStart, Length);
119
120                         Count += Length;
121
122                         AllocatedCount = NewCount;
123                         HeapValPtr = DataPtr;
124
125                         HeapValPtr[Count] = 0;
126                     }
127                 }
128             }
129
130             const TCharType* CStr() const
131             {
132                 return GetDataPtr();
133             }
134
135             // is is a internal function
136             //
137             void InjectAdd(SIZE_T InCount)
138             {
139                 Count += InCount;
140
141                 assert(IsDataOnStack() ? (Count <= DEFAULT_LENGTH) : (Count < AllocatedCount));
142             }
143
144         protected:
145             void  AddItem(const TCharType& InValue)
146             {
147                 Super::AddItem(InValue);
148             }
149         };

上面展示的是基于栈内存容器实现的栈字符串,在大多数情况下,我们格式化字符串时都采用栈字符串来保存结果,这样可以显著的提升性能。

同时栈容器和栈字符串,都特别适合于当临时容器和临时字符串,因为多数情况下它们都优化掉了可能需要动态内存分配的操作。所以它们的使用并不局限于这一个小地方。

4. 基于C++ 11的优化

除了引入了C++ 11的容器unordered_map之外,还引入了右值引用等新内容,在某些情况下,可以带来一定的性能提升。

 1 #if FL_PLATFORM_HAS_RIGHT_VALUE_REFERENCE
 2             TAutoArray( SelfType && Other ) :
 3                 Count(Other.Count),
 4                 AllocatedCount(Other.AllocatedCount),
 5                 HeapValPtr(Other.HeapValPtr)
 6             {
 7                 if (Count > 0 && Other.IsDataOnStack())
 8                 {
 9                     Algorithm::MoveArray(Other.StackVal, Other.StackVal + Count, StackVal);
10                 }
11
12                 Other.Count = 0;
13                 Other.AllocatedCount = 0;
14                 Other.HeapValPtr = NULL;
15             }
16
17             SelfType& operator = (SelfType&& Other )
18             {
19                 return TakeFrom(Other);
20             }
21 #endif

上面展示的是基于右值引用的优化。

除此之外还是用了线程局部存储(TLS),这依赖于编译器是否支持。前面提到了我们采用Hash容器来存储Pattern缓存,然而在单线程的时候自然无需多余考虑,当需要支持多线程时,则全局唯一的Hash容器的访问都需要加锁,而加锁是有性能开销的。幸好C++ 11带来了内置的TLS支持,其结果就是每个线程会独立保存一份这样的Pattern缓存,因此无需对其访问加锁,这样无疑效率会更高。缺陷则是会损失部分内存。所有的这些都可以通过预先的宏定义来进行开关,使用者可以自行决定使用TLS还是Lock,或者不支持多线程。

 1         template < typename TPolicy >
 2         class TGlobalPatternStorage :
 3             public TPatternStorage<TPolicy>
 4         {
 5         public:
 6             static TGlobalPatternStorage* GetStorage()
 7             {
 8 #if FL_WITH_THREAD_LOCAL
 9                 struct ManagedStorage
10                 {
11                     typedef Utility::TScopedLocker<System::CriticalSection>  LockerType;
12
13                     System::CriticalSection                                  ManagedCS;
14                     Utility::TAutoArray<TGlobalPatternStorage*>              Storages;
15
16                     ~ManagedStorage()
17                     {
18                         LockerType Locker(ManagedCS);
19
20                         for( SIZE_T i=0; i<Storages.GetLength(); ++i )
21                         {
22                             delete Storages[i];
23                         }
24                     }
25
26                     void AddStorage( TGlobalPatternStorage* Storage )
27                     {
28                         assert(Storage);
29
30                         LockerType Locker(ManagedCS);
31
32                         Storages.AddItem(Storage);
33                     }
34                 };
35
36                 static ManagedStorage StaticManager;
37
38                 static FL_THREAD_LOCAL TGlobalPatternStorage* StaticStorage = NULL;
39
40                 if( !StaticStorage )
41                 {
42                     StaticStorage = new TGlobalPatternStorage();
43
44                     StaticManager.AddStorage(StaticStorage);
45                 }
46
47                 return StaticStorage;
48 #else
49                 static TGlobalPatternStorage StaticStorage;
50                 return &StaticStorage;
51 #endif
52             }
53         };

如上所示为项目中使用TLS的代码。

总结

在将这一系列的优化结合起来之后,可以使得FL的整体效率处于较高水平,不低于C库函数,同时还具备其它格式化库不具备的功能,对于代码安全性等各方面的增强,都有帮助。下面是Test.cpp的测试结果,FL代表的是使用FL库的耗时,CL代表的C库的耗时,同时此测试模拟了多线程环境。

Windows Visual Studio 2013 Release下的输出:

0x64
Test20, -10.0050,  X ,  X
0x64
Test20, -10.0050,  X ,  X
1920 FLElapse:0.0762746
1920 CLElapse:0.269722
1636 FLElapse:0.0756153
7732 FLElapse:0.0766446
7956 FLElapse:0.0762051
7956 CLElapse:0.285714
1636 CLElapse:0.288648
7732 CLElapse:0.289193

Mac Xcode Release:

99
Test20, -10.0050,  X ,  X
18446744073709551615 FLElapse:0.0901681
18446744073709551615 CLElapse:0.19329
18446744073709551615 FLElapse:0.147378
18446744073709551615 FLElapse:0.150375
18446744073709551615 FLElapse:0.153342
18446744073709551615 CLElapse:0.303508
18446744073709551615 CLElapse:0.308418
18446744073709551615 CLElapse:0.307407

这并非完全的测试,更多的测试需要在实际使用过程中来验证。

时间: 2024-08-01 23:20:16

CPPFormatLibary提升效率的优化原理的相关文章

paip.提升效率--数据绑定到table原理和流程Angular js jquery实现

paip.提升效率--数据绑定到table原理和流程Angular js  jquery实现 html #--keyword 1 #---原理和流程 1 #----jq实现的代码 1 #-----Angular 的实现 3 #--keyword jquery 遍历表格tr  td Angular 模板绑定 #---原理和流程 获得所有的行,第一的头行..排除,,,在的所有的删除. 遍历表格tr获得tds的所有的id数组. 根据id/id索引来获得绑定的数据源里面的数据字段..绑定到个td上..

我必须得告诉你的MySQL优化原理3

聊聊MySQL配置. 大多数开发者可能不太会关注MySQL的配置,毕竟在基本配置没有问题的情况下,把更多的精力放在schema设计.索引优化和SQL优化上,是非常务实的策略.这时,如果再花力气去优化配置项,获得的收益通常都比较小.更多的时候,基于安全因素的考量,普通开发者很少能够接触到生产环境的MySQL配置.正是这样,导致开发者(包括我)对MySQL的配置不甚了解,希望本文能帮你更好的了解MySQL配置. 如果让你在某种环境上安装配置MySQL,你会怎么做?安装后,直接copy修改示例配置文件

MySQL Optimization 优化原理

MySQL Optimization 优化原理 MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图. MySQL逻辑架构,来自:高性能MySQL MySQL逻辑架构整体分为三层,最上层为客户端层,并非MySQL所独有,诸如:连接处理.授权认证.安全等功能均在这一层处理. MySQL大多数核心服务均在中间这一层,包括查询解析.分析.优化.缓存.内置函数(比如:时间.数学.加密等函数).所有的跨存储引擎

mysql优化原理,一定要看懂

转:     https://www.jianshu.com/p/d7665192aaaf 我必须得告诉大家的MySQL优化原理 说起MySQL的查询优化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的工作原理?在实际场景下性能真有提升吗?我想未必.因而理解这些优化建议背后的原理就尤为重要,希望本文能让你重新审视这些优化建议,并在实际业务场景下合理的运用. MySQL逻辑架构

深入理解MySQL优化原理

说起MySQL的查询优化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的工作原理?在实际场景下性能真有提升吗?我想未必.因而理解这些优化建议背后的原理就尤为重要,希望本文能让你重新审视这些优化建议,并在实际业务场景下合理的运用. MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图

atitit groovy 总结java 提升效率

atitit groovy 总结java 提升效率 #---环境配置 1 #------安装麻烦的 2 三.创建groovy项目 2 3.  加入? Groovy 类 2 4.  编译执行groovy类 3 Groovy断点调试不生效的解决 4 Groovy实现执行原理 5 1. Groovy脚本的执行.. 5 2. Groovy类的执行.. 5 Groovy语法长处: 6 3. 动态类型def 6 4. 循环变量不须要def 6 5. String 和Gstring 6 6. 范围 6 7. 

mysql数据库的优化和查询效率的优化

一.数据库的优化 1.优化索引.SQL 语句.分析慢查询: 2.设计表的时候严格根据数据库的设计范式来设计数据库: 3.使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO: 4.优化硬件:采用SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等: 5.采用MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率: 6.垂直分表:把一些不经常读的数据放在一张表里,节约磁盘I/O: 7.主从分离读写:采用主从复制把数据库的读操作和写入操作

提升效率的Linux终端快捷操作汇总

很多普通 Linux 桌面用户都对使用终端感到排斥和恐惧,其实它没大家想的那么复杂,很多常见操作都可以直接在终端中进行,如:安装软件.升级系统等. 无论你是新手还是 Linux 终端使用的老鸟,系统极客在此为大家总结了提升终端命令执行效率的快捷操作汇总,希望能帮助你学习和提升效率. 移动定位光标 在终端中移动光标和定位似乎非常不便,其实不是你想的那样,有很多种方式可以让键盘成为你的好朋友,只是需要掌握正确的方法而已. 定位单词 在长段的命令中,使用 Ctrl + ← 和 Ctrl + → 可快速

Android中的自定义Adapter(继承自BaseAdapter)——与系统Adapter的调用方法一致——含ViewHolder显示效率的优化(转)

Android中很多地方使用的是适配器(Adapter)机制,那我们就要好好把这个Adapter利用起来,并且用出自己的特色,来符合我们自行设计的需要喽~~~ 下面先上一个例子,是使用ViewHolder进行显示效率优化过的工程: package com.test.listviewsimpleadapter;    import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;  import java