Shmem по сравнению с tmpfs по сравнению с [закрытым] mmap

Есть важная, но почти всегда пропущенная особенность оператора 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
11
задан Jonathan Leffler 24 May 2009 в 21:43
поделиться

4 ответа

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
#
8
ответ дан 3 December 2019 в 10:05
поделиться

"Это зависит". В общем, все они находятся в памяти и зависят от реализации системы, поэтому производительность будет незначительной и зависит от платформы для большинства применений. Если вы действительно заботитесь о производительности, вам следует профилировать и определить свои требования. Заменить один из этих методов другим довольно тривиально.

Тем не менее, разделяемая память наименее интенсивна, поскольку не требует операций с файлами (но опять же, очень зависит от реализации). Если вам нужно многократно открывать и закрывать (отображать / отменять отображение), много раз, это может быть значительными накладными расходами.

Ура!
Шон

2
ответ дан 3 December 2019 в 10:05
поделиться

Под «общей памятью» вы подразумеваете разделяемую память System V, верно?

Я думаю, что Linux mmap - это скрытый tmpfs, когда вы его используете, так что это фактически то же самое, что mmaping tmpfs.

Выполнение файлового ввода-вывода на tmpfs будет иметь штраф ... в основном (есть особые случаи, когда это может иметь смысл, например> 4G в 32-битном процессе)

1
ответ дан 3 December 2019 в 10:05
поделиться

tmpfs - самый медленный. Общая память и mmap имеют одинаковую скорость.

-1
ответ дан 3 December 2019 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: