Есть важная, но почти всегда пропущенная особенность оператора Mid (). Вот где Mid () появляется в левой части назначения, в отличие от функции Mid (), которая появляется в правой части или в выражении.
Правило состоит в том, что если целевая строка не является строковым литералом, и это единственная ссылка на целевую строку, а длина вставляемого сегмента соответствует длине заменяемого сегмента, то строка будет быть обработанным как изменчивый для операции.
Что это значит? Это означает, что если вы создаете большой отчет или огромный список строк в одно строковое значение, то использование этого сделает вашу обработку строк намного быстрее.
Вот простой класс, который выигрывает от этого. Он дает вашему VBA такую же возможность StringBuilder, что и .Net.
' Class: StringBuilder
Option Explicit
Private Const initialLength As Long = 32
Private totalLength As Long ' Length of the buffer
Private curLength As Long ' Length of the string value within the buffer
Private buffer As String ' The buffer
Private Sub Class_Initialize()
' We set the buffer up to it's initial size and the string value ""
totalLength = initialLength
buffer = Space(totalLength)
curLength = 0
End Sub
Public Sub Append(Text As String)
Dim incLen As Long ' The length that the value will be increased by
Dim newLen As Long ' The length of the value after being appended
incLen = Len(Text)
newLen = curLength + incLen
' Will the new value fit in the remaining free space within the current buffer
If newLen <= totalLength Then
' Buffer has room so just insert the new value
Mid(buffer, curLength + 1, incLen) = Text
Else
' Buffer does not have enough room so
' first calculate the new buffer size by doubling until its big enough
' then build the new buffer
While totalLength < newLen
totalLength = totalLength + totalLength
Wend
buffer = Left(buffer, curLength) & Text & Space(totalLength - newLen)
End If
curLength = newLen
End Sub
Public Property Get Length() As Integer
Length = curLength
End Property
Public Property Get Text() As String
Text = Left(buffer, curLength)
End Property
Public Sub Clear()
totalLength = initialLength
buffer = Space(totalLength)
curLength = 0
End Sub
А вот пример того, как его использовать:
Dim i As Long
Dim sb As StringBuilder
Dim result As String
Set sb = New StringBuilder
For i = 1 to 100000
sb.Append CStr( i)
Next i
result = sb.Text
Read about tmpfs
here. The following is copied from that article, explaining the relation between shared memory and tmpfs
in particular.
1) There is always a kernel internal mount which you will not see at
all. This is used for shared anonymous mappings and SYSV shared
memory.
This mount does not depend on CONFIG_TMPFS. If CONFIG_TMPFS is not
set the user visible part of tmpfs is not build, but the internal
mechanisms are always present.
2) glibc 2.2 and above expects tmpfs to be mounted at /dev/shm for
POSIX shared memory (shm_open, shm_unlink). Adding the following
line to /etc/fstab should take care of this:
tmpfs /dev/shm tmpfs defaults 0 0
Remember to create the directory that you intend to mount tmpfs on
if necessary (/dev/shm is automagically created if you use devfs).
This mount is _not_ needed for SYSV shared memory. The internal
mount is used for that. (In the 2.3 kernel versions it was
necessary to mount the predecessor of tmpfs (shm fs) to use SYSV
shared memory)
So, when you actually use POSIX shared memory (which i used before, too), then glibc
will create a file at /dev/shm
, which is used to share data between the applications. The file-descriptor it returns will refer to that file, which you can pass to mmap
to tell it to map that file into memory, like it can do with any "real" file either. The techniques you listed are thus complementary. They are not competing. Tmpfs
is just the file-system that provides in-memory files as an implementation technique for glibc
.
As an example, there is a process running on my box currently having registered such a shared memory object:
# pwd
/dev/shm
# ls -lh
insgesamt 76K
-r-------- 1 js js 65M 24. Mai 16:37 pulse-shm-1802989683
#
"Это зависит". В общем, все они находятся в памяти и зависят от реализации системы, поэтому производительность будет незначительной и зависит от платформы для большинства применений. Если вы действительно заботитесь о производительности, вам следует профилировать и определить свои требования. Заменить один из этих методов другим довольно тривиально.
Тем не менее, разделяемая память наименее интенсивна, поскольку не требует операций с файлами (но опять же, очень зависит от реализации). Если вам нужно многократно открывать и закрывать (отображать / отменять отображение), много раз, это может быть значительными накладными расходами.
Ура!
Шон
Под «общей памятью» вы подразумеваете разделяемую память System V, верно?
Я думаю, что Linux mmap - это скрытый tmpfs, когда вы его используете, так что это фактически то же самое, что mmaping tmpfs.
Выполнение файлового ввода-вывода на tmpfs будет иметь штраф ... в основном (есть особые случаи, когда это может иметь смысл, например> 4G в 32-битном процессе)
tmpfs - самый медленный. Общая память и mmap имеют одинаковую скорость.