Sich selbst überschreibender Buffer

    • VB.NET

    Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von FreakJNS.

      Sich selbst überschreibender Buffer

      Ich habe gestern einen Klasse zum Speichern von größeren Datenmengen gebraucht, ohne jedoch einen gewissen Speicherverbrauch zu überschreiten. Leider habe ich nix fertiges gefunden also habe ich schnell selber einen Art Buffer geschrieben welcher ein Array besitzt, welches sich selbst überschreibt wenn der Buffer voll ist. Ich hab es gestern Abend geschrieben und von dem her ist die Klasse vll. noch optimierungs fähig. Wäre dankbar über Vorschläge. Ich poste mal unten den Code (ist von C# konvertiert) und falls wiedermal jemand im Netz sowas sucht(wie ich) findet er es dann hoffentlich.

      Code

      VB.NET-Quellcode

      1. Public Class StaticBuffer(Of T) : Implements IDisposable 'optional auch von System.IO.Stream ableiten
      2. Private _buffer As T() 'buffer welcher immer wieder überschrieben wird
      3. Private _bufferedBytes As Integer = 0 'anzahl der vorhandenen Bytes
      4. Private _writeOffset As Integer = 0 'Schreibeoffset im Buffer
      5. Private _readOffset As Integer = 0 'Leseoffset im Buffer
      6. Private _lockObj As New Object()
      7. Public Sub New(ByVal bufferSize As Integer)
      8. _buffer = New T(bufferSize - 1) {}
      9. End Sub
      10. Public Function Write(ByVal buffer As T(), ByVal offset As Integer, ByVal count As Integer) As Integer
      11. Dim written As Integer = 0
      12. SyncLock _lockObj
      13. If count > _buffer.Length - _bufferedBytes Then
      14. count = _buffer.Length - _bufferedBytes
      15. End If
      16. Dim length As Integer = Math.Min(count, _buffer.Length - _writeOffset)
      17. Array.Copy(buffer, offset, _buffer, _writeOffset, length) 'copy to buffer
      18. _writeOffset += length
      19. written += length
      20. _writeOffset = _writeOffset Mod _buffer.Length
      21. 'WENN GERADE ENDE DES ARRAYS ÜBERSCHRITTEN WURDE:
      22. If written < count Then
      23. Array.Copy(buffer, offset + written, _buffer, _writeOffset, count - written)
      24. _writeOffset += (count - written)
      25. written += (count - written)
      26. End If
      27. _bufferedBytes += written
      28. End SyncLock
      29. Return written
      30. End Function
      31. Public Function Read(ByVal buffer As T(), ByVal offset As Integer, ByVal count As Integer) As Integer
      32. Dim rd As Integer = 0
      33. SyncLock _lockObj
      34. count = Math.Min(count, _bufferedBytes)
      35. Dim length As Integer = Math.Min(count, _buffer.Length - _readOffset)
      36. Array.Copy(_buffer, _readOffset, buffer, offset, length) 'copy to buffer
      37. _readOffset = _readOffset Mod _buffer.Length
      38. Read += length
      39. _readOffset += Read
      40. 'WENN GERADE ENDE DES ARRAYS ÜBERSCHRITTEN WURDE:
      41. If Read < count Then
      42. Array.Copy(_buffer, _readOffset, buffer, offset + Read, count - Read)
      43. _readOffset += (count - Read)
      44. Read += (count - Read)
      45. End If
      46. _bufferedBytes -= Read
      47. End SyncLock
      48. Return Read
      49. End Function
      50. Public ReadOnly Property Length() As Integer
      51. Get
      52. Return _buffer.Length
      53. End Get
      54. End Property
      55. Public ReadOnly Property Buffered() As Integer
      56. Get
      57. Return _bufferedBytes
      58. End Get
      59. End Property
      60. Public Sub Clear()
      61. Array.Clear(_buffer, 0, _buffer.Length) 'alle offsets zurücksetzen
      62. _bufferedBytes = 0
      63. _writeOffset = 0
      64. _readOffset = 0
      65. End Sub
      66. Public Sub Dispose() Implements IDisposable.Dispose
      67. _buffer = Nothing
      68. End Sub
      69. End Class

      Anwendungen:

      Eine Anwendung wäre z.B. wenn man z.B. irgendetwas vom Internet Streamt, Chats programmiert etc. den Buffer so verwenden kann, dass man das gestreamte dort drinnen speichert und anschließend ausgibt. Ist es ausgegeben, wird es nicht mehr benötigt und kann weggeworfen werden. Als Resultat hat man einen kontinuierlichen Stream welcher aber nicht immer mehr Speicher braucht.
      Hier noch ein kleines Beispiel wo ich das z.B. gebraucht habe(stream von ö3 - radio):
      youtube.com/watch?v=RccSkY0gyJc&feature=channel&list=UL


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

      Nö kannste ich nicht. Außerdem wird dies erst ab .net 4.0 verwendet. Manche schreiben aber auf 2.0 oder 3.0(und bevor hier die ganzen .net 4.5 Fanatiker kommen muss ich sagen, dass es sehr wohl Sinn macht gewisse Dinge in .net 2.0 zu machen - gerade auch Bibliotheken etc.).Und wer legt die größe Fest?
      Das würde nicht die Funktionalität haben welche ich gebraucht habe.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Habs nicht genau angeschaut. Könnte jedoch vom Prinzip her ähnlich sein. Jedoch wäre dieser für manche Dinge viel zu unperformant. Außerdem wenn mein Buffer eine größe von 10 hat und du haust das 11. element rein gehts halt wieder auf index 0. Ob dann jemand vorher das 0. element welches überschrieben wird gelesen hat oder nicht interessiert ihn nicht. Wie gesagt ist hauptsächlich darauf ausgelegt große Datenmengen schnell und einfach buffern zu können ohne den Speicherverbrauch ins unendliche zu treiben. Wie bereits gesagt Anwendungsbeispiel z.B. Sprachchat.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

      thefiloe schrieb:

      Könnte jedoch vom Prinzip her ähnlich sein.

      Das "Problem" ist, dass sich das ganze im Prinzip extremst trivial lösen läßt ... nämlich wie bereits angesprochen mit einer Queue

      VB.NET-Quellcode

      1. Public Class FixedBuffer(Of T)
      2. Private _TheQueue As New Queue(Of T)
      3. Private _MaxCapacity
      4. Public Sub New(Capacity As Integer)
      5. _MaxCapacity = Capacity
      6. End Sub
      7. Private ReadOnly Property Count As Integer
      8. Get
      9. Return _TheQueue.Count
      10. End Get
      11. End Property
      12. Public Sub Enqueue(ByVal o As T)
      13. While _TheQueue.Count >= _MaxCapacity
      14. _TheQueue.Dequeue()
      15. End While
      16. _TheQueue.Enqueue(o)
      17. End Sub
      18. Public Function Dequeue() As T
      19. Return _TheQueue.Dequeue
      20. End Function
      21. End Class
      Vom Prinzip ja nur sie nicht für die Anwendungsbereiche ausgelegt. Ich hatte dies auch getestet doch bei einem Datenfluss von z.b. 350000 Bytes pro Sekunde und das noch alles in Realtime wird ne Queue einfach an ihre Grenzen gebracht. Das kannste jetzt glauben oder nicht aber das Teil ist nicht darauf ausgelegt. Wenn du von mir aus 50000 Bytes (was noch relativ wenig ist) haben möchtest musst du 50.000 mal Dequeue aufrufen. Das ist einfach overkill. Außerdem ist dadurch auch nicht gewährleistet, dass der Speicherverbrauch nichts überschreitet. Bleiben wir bei dem Beispiel, dass du nen Livestream Bufferst. Sagen wir du schreibst einen Stream dafür welcher fröhlich vor sich her buffert. Was ist wenn du die Daten nicht abholst? Ne drehs wie du es willst für gewisse Dinge gibts im Framework nix. So habs nochmal extra getestet. Mit Queue knackst es und ist zu langsam + Prozessorauslastung ist höher ohne funktioniert tadellos.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „thefiloe“ ()

      ich würde zusätzlich die Bytes in kleinen Packen ablegen. Also statt 350000 Einzelbytes z.B. nur 342 Pakete von je 1KB. Könntest dafür einen kleineren Buffer anlegen, der wartet bis ein KB voll ist und dann alles in die Queue schiebt - würde sich wunderbar in picoflops code einbauen lassen. Ein Bytearray würde für den unteresten Puffer reichen

      (oder schreibst du die Tafel auch Buchstabenweise ab? xD)

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „FreakJNS“ ()