vortexpy 4.0.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. vortex/DataWrapTuple.py +27 -0
  2. vortex/DeferUtil.py +224 -0
  3. vortex/Jsonable.py +304 -0
  4. vortex/Payload.py +115 -0
  5. vortex/PayloadEndpoint.py +216 -0
  6. vortex/PayloadEndpointTest.py +164 -0
  7. vortex/PayloadEnvelope.py +166 -0
  8. vortex/PayloadFilterKeys.py +15 -0
  9. vortex/PayloadIO.py +152 -0
  10. vortex/PayloadPriority.py +11 -0
  11. vortex/PayloadResponse.py +173 -0
  12. vortex/PayloadResponseTest.py +39 -0
  13. vortex/PayloadTest.py +136 -0
  14. vortex/PerformTestActionTuple.py +30 -0
  15. vortex/SerialiseUtil.py +273 -0
  16. vortex/TestTuple.py +61 -0
  17. vortex/Tuple.py +968 -0
  18. vortex/TupleAction.py +72 -0
  19. vortex/TupleActionVortex.py +5 -0
  20. vortex/TupleDataForTest.py +25 -0
  21. vortex/TuplePerfTest.py +71 -0
  22. vortex/TuplePolymorphicTupleTypeFieldArgTest.py +74 -0
  23. vortex/TupleRestfulTest.py +140 -0
  24. vortex/TupleSelector.py +105 -0
  25. vortex/TupleTest.py +127 -0
  26. vortex/VortexABC.py +55 -0
  27. vortex/VortexClientHttp.py +308 -0
  28. vortex/VortexClientHttpTest.py +71 -0
  29. vortex/VortexClientTcp.py +355 -0
  30. vortex/VortexClientWebsocketFactory.py +383 -0
  31. vortex/VortexConnectionABC.py +88 -0
  32. vortex/VortexFactory.py +932 -0
  33. vortex/VortexPayloadProtocol.py +180 -0
  34. vortex/VortexServer.py +367 -0
  35. vortex/VortexServerConnection.py +127 -0
  36. vortex/VortexServerHttpResource.py +193 -0
  37. vortex/VortexServerTcp.py +104 -0
  38. vortex/VortexServerWebsocket.py +287 -0
  39. vortex/VortexTcpMemoryLeakPayloadTest.py +611 -0
  40. vortex/VortexTcpMemoryLeakRawTest.py +87 -0
  41. vortex/VortexTest.py +22 -0
  42. vortex/VortexUtil.py +314 -0
  43. vortex/VortexWritePushProducer.py +321 -0
  44. vortex/__init__.py +10 -0
  45. vortex/data_loader/TupleDataLiveLockManager.py +383 -0
  46. vortex/data_loader/TupleDataLoader.py +326 -0
  47. vortex/data_loader/TupleDataLoaderDelegate.py +90 -0
  48. vortex/data_loader/TupleDataLoaderTupleABC.py +10 -0
  49. vortex/data_loader/TupleDataLoaderTuples.py +53 -0
  50. vortex/data_loader/__init__.py +0 -0
  51. vortex/event_bus/TupleChangeEventABC.py +15 -0
  52. vortex/event_bus/TupleChangeEventBus.py +192 -0
  53. vortex/event_bus/TupleChangeEventBusObserverABC.py +11 -0
  54. vortex/event_bus/__init__.py +0 -0
  55. vortex/handler/TupleActionProcessor.py +270 -0
  56. vortex/handler/TupleActionProcessorProxy.py +218 -0
  57. vortex/handler/TupleActionProcessorTestHandler.py +27 -0
  58. vortex/handler/TupleDataActionClient.py +67 -0
  59. vortex/handler/TupleDataObservableCache.py +201 -0
  60. vortex/handler/TupleDataObservableHandler.py +371 -0
  61. vortex/handler/TupleDataObservableProxyHandler.py +340 -0
  62. vortex/handler/TupleDataObservableTestHandler.py +60 -0
  63. vortex/handler/TupleDataObserverClient.py +158 -0
  64. vortex/handler/VortexJSTupleLoaderTestHandler.py +42 -0
  65. vortex/handler/__init__.py +0 -0
  66. vortex/restful/GzippedDataHttpClient.py +170 -0
  67. vortex/restful/GzippedDataHttpClientTest.py +103 -0
  68. vortex/restful/GzippedPayloadHttpClient.py +181 -0
  69. vortex/restful/RestfulHttpClient.py +107 -0
  70. vortex/restful/RestfulHttpClientTest.py +60 -0
  71. vortex/restful/RestfulResource.py +153 -0
  72. vortex/restful/RestfulResourceTest.py +100 -0
  73. vortex/restful/__init__.py +0 -0
  74. vortex/rpc/RPC.py +446 -0
  75. vortex/rpc/RPCTest.py +12 -0
  76. vortex/rpc/__init__.py +0 -0
  77. vortex/sqla_orm/OrmCrudHandler.py +431 -0
  78. vortex/sqla_orm/TupleProviderForDb.py +42 -0
  79. vortex/sqla_orm/VortexTupleJson.py +24 -0
  80. vortex/sqla_orm/__init__.py +0 -0
  81. vortex/storage/TupleStorageSqlite.py +359 -0
  82. vortex/storage/__init__.py +0 -0
  83. vortexpy-4.0.23.dist-info/LICENSE +21 -0
  84. vortexpy-4.0.23.dist-info/METADATA +43 -0
  85. vortexpy-4.0.23.dist-info/RECORD +87 -0
  86. vortexpy-4.0.23.dist-info/WHEEL +5 -0
  87. vortexpy-4.0.23.dist-info/top_level.txt +1 -0
@@ -0,0 +1,611 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+ import gc
10
+ import os
11
+ import tracemalloc
12
+ from collections import deque
13
+ from random import random
14
+ from typing import Optional
15
+
16
+ import psutil
17
+ from twisted.internet import reactor
18
+ from twisted.internet.defer import inlineCallbacks, Deferred
19
+ from twisted.python.failure import Failure
20
+ from twisted.trial import unittest
21
+
22
+ from vortex.Payload import Payload
23
+ from vortex.PayloadEndpoint import PayloadEndpoint
24
+ from vortex.VortexClientTcp import VortexClientTcp
25
+ from vortex.VortexServer import VortexServer
26
+ from vortex.VortexServerTcp import VortexTcpServerFactory
27
+
28
+
29
+ class MemoryCheckerTestMixin:
30
+ def _memMark(self):
31
+ self._process = psutil.Process(os.getpid())
32
+ unreachable = gc.collect()
33
+ self._initialMem = self._process.memory_info().rss
34
+ self._initialUnreachable = unreachable
35
+ self._lastMem = self._initialMem
36
+
37
+ def _memCheck(self, grace=0):
38
+ unreachable = gc.collect()
39
+ self.assertLessEqual(
40
+ unreachable,
41
+ self._initialUnreachable,
42
+ "The garbage collector couldn't release everything",
43
+ )
44
+ self._memPrintIncrease()
45
+ memNow = self._process.memory_info().rss
46
+ self.assertLessEqual(memNow, self._initialMem + grace)
47
+
48
+ def _memPrintIncrease(self, printOnlyOnGrowth=False):
49
+ gc.collect()
50
+ memNow = self._process.memory_info().rss
51
+ thisDiff = memNow - self._initialMem
52
+ lastDiff = self._lastMem - self._initialMem
53
+ growth = thisDiff - lastDiff
54
+ self._lastMem = memNow
55
+ if not printOnlyOnGrowth or growth:
56
+ print(
57
+ "Memory growth is %s, total growth %s, total %s"
58
+ % (
59
+ "{:,d}".format(growth),
60
+ "{:,d}".format(thisDiff),
61
+ "{:,d}".format(memNow),
62
+ )
63
+ )
64
+
65
+ def _memCheckFunction(self, callable, loopCount, *args, **kwargs):
66
+ assert loopCount >= 10, "We need at least 10 loops to check this"
67
+ # Give the memory 5 loops to warmed up, it shouldn't need more than 2
68
+ startMemIndex = 5
69
+ for index in range(loopCount):
70
+ if index == startMemIndex: # Mark the second loop only
71
+ self._memMark()
72
+
73
+ callable(*args, **kwargs)
74
+
75
+ if startMemIndex <= index:
76
+ self._memPrintIncrease(printOnlyOnGrowth=True)
77
+
78
+ self._memCheck(grace=0)
79
+
80
+
81
+ class VortexTcpConnectTestMixin:
82
+ @inlineCallbacks
83
+ def _connect(self):
84
+ port = 20000 + int(random() * 10000)
85
+
86
+ # Create the server
87
+ self._vortexServer = VortexServer("test server")
88
+ vortexTcpServerFactory = VortexTcpServerFactory(self._vortexServer)
89
+ self._listenPort = reactor.listenTCP(port, vortexTcpServerFactory)
90
+
91
+ # Create the client
92
+ self._vortexClient = VortexClientTcp("test client")
93
+ yield self._vortexClient.connect("127.0.0.1", port)
94
+
95
+ def _disconnect(self):
96
+ self._listenPort.stopListening()
97
+ del self._listenPort
98
+
99
+ self._vortexServer.shutdown()
100
+ del self._vortexServer
101
+
102
+ self._vortexClient.close()
103
+ del self._vortexClient
104
+
105
+
106
+ class VortexSendReceiveTestMixin:
107
+ # Setup a queue state
108
+ _loopbackFilt = {"key": "unittest"}
109
+
110
+ class _State:
111
+ def __init__(self, testSelf, sendFromServerOnly):
112
+ self.testSelf = testSelf
113
+ self.sendFromServerOnly = sendFromServerOnly
114
+
115
+ self.dataSizeStats = []
116
+ self.vortexSizeStats = []
117
+
118
+ self.dataQueue = deque()
119
+ self.dataQueueEmptyDeferred = Deferred()
120
+ self.totalSent = 0
121
+ self.totalReceived = 0
122
+ self.totalMessagesSent = 0
123
+ self.totalMessagesReceived = 0
124
+ self.totalMessagesOutOfOrder = 0
125
+ self.highestOutOfOrderIndex = 0
126
+
127
+ self.totalSentFromClient = 0
128
+ self.totalSentFromServer = 0
129
+
130
+ def vortex(self, dataLen: int):
131
+ if not self.sendFromServerOnly and random() < 0.5:
132
+ self.totalSentFromClient += dataLen
133
+ return self.testSelf._vortexClient
134
+
135
+ self.totalSentFromServer += dataLen
136
+ return self.testSelf._vortexServer
137
+
138
+ class _Checker:
139
+ def __init__(self, testSelf, state, printStatusEveryXMessage):
140
+ self.endpoint = None
141
+ self.testSelf = testSelf
142
+ self.state = state
143
+ self.printStatusEveryXMessage = printStatusEveryXMessage
144
+
145
+ def setEndpoint(self, endpoint):
146
+ self.endpoint = endpoint
147
+
148
+ # Setup the receiver of the data
149
+ @inlineCallbacks
150
+ def process(self, payloadEnvelope, *args, **kwargs):
151
+ try:
152
+ payload = yield payloadEnvelope.decodePayloadDefer()
153
+ dataReceived = payload.tuples[0]
154
+ self.state.totalReceived += len(dataReceived)
155
+ self.state.totalMessagesReceived += 1
156
+
157
+ dataSent = None
158
+ for index, item in enumerate(self.state.dataQueue):
159
+ if item == dataReceived:
160
+ dataSent = dataReceived
161
+ if index:
162
+ self.state.totalMessagesOutOfOrder += 1
163
+ self.state.highestOutOfOrderIndex = max(
164
+ self.state.highestOutOfOrderIndex, index
165
+ )
166
+ self.state.dataQueue.remove(item)
167
+
168
+ else:
169
+ self.state.dataQueue.popleft()
170
+
171
+ break
172
+
173
+ if not (
174
+ self.state.totalMessagesReceived
175
+ % self.printStatusEveryXMessage
176
+ ):
177
+ print(
178
+ "Received message %s, this %s, total %s"
179
+ % (
180
+ self.state.totalMessagesReceived,
181
+ "{:,d}".format(len(dataReceived)),
182
+ "{:,d}".format(self.state.totalReceived),
183
+ )
184
+ )
185
+
186
+ self.testSelf.assertEqual(dataReceived, dataSent)
187
+
188
+ if not self.state.dataQueue:
189
+ self.state.dataQueueEmptyDeferred.callback(True)
190
+
191
+ except Exception as e:
192
+ self.endpoint.shutdown()
193
+ self.state.dataQueueEmptyDeferred.errback(Failure(e))
194
+
195
+ @inlineCallbacks
196
+ def _vortexTestTcpServerClient(
197
+ self,
198
+ printStatusEveryXMessage: Optional[int] = 1000,
199
+ maxMessageSizeBytes: Optional[int] = None,
200
+ exactMessageSizeBytes: Optional[int] = None,
201
+ totalBytesToSend: Optional[int] = None,
202
+ totalMessagesToSend: Optional[int] = None,
203
+ payloadCompression=9,
204
+ sendFromServerOnly=False,
205
+ ):
206
+ assert (
207
+ totalBytesToSend or totalMessagesToSend
208
+ ), "We must have a total to send"
209
+ assert (
210
+ maxMessageSizeBytes or exactMessageSizeBytes
211
+ ), "We must have a msg size"
212
+
213
+ state = self._State(self, sendFromServerOnly)
214
+ checker = self._Checker(self, state, printStatusEveryXMessage)
215
+ endpoint = PayloadEndpoint(self._loopbackFilt, checker.process)
216
+ checker.setEndpoint(endpoint)
217
+
218
+ # Make random chunks of data
219
+ def makeData():
220
+ size = (
221
+ random() * maxMessageSizeBytes
222
+ if exactMessageSizeBytes is None
223
+ else exactMessageSizeBytes
224
+ )
225
+
226
+ packet = str(random())
227
+ while len(packet) < size:
228
+ packet += str(random())
229
+
230
+ if exactMessageSizeBytes is not None:
231
+ packet = packet[:exactMessageSizeBytes]
232
+
233
+ return packet
234
+
235
+ def check():
236
+ if (
237
+ totalMessagesToSend
238
+ and state.totalMessagesSent < totalMessagesToSend
239
+ ):
240
+ return True
241
+
242
+ if totalBytesToSend and state.totalSent < totalBytesToSend:
243
+ return True
244
+
245
+ return False
246
+
247
+ # Send the data
248
+ while check():
249
+ data = makeData()
250
+ state.dataQueue.append(data)
251
+ state.totalSent += len(data)
252
+ state.totalMessagesSent += 1
253
+
254
+ vortexMsg = yield Payload(
255
+ self._loopbackFilt, data
256
+ ).makePayloadEnvelopeVortexMsgDefer(
257
+ compressionLevel=payloadCompression
258
+ )
259
+
260
+ state.dataSizeStats.append(len(data))
261
+ state.vortexSizeStats.append(len(vortexMsg))
262
+
263
+ # We could send this from either the vortexClient or vortexServer
264
+ # We only have one PayloadIO that the PayloadEndpoint binds to anyway
265
+ state.vortex(len(data)).sendVortexMsg(vortexMsg)
266
+
267
+ if not (state.totalMessagesSent % printStatusEveryXMessage):
268
+ print(
269
+ "Sent message %s, this %s, total %s"
270
+ % (
271
+ state.totalMessagesSent,
272
+ "{:,d}".format(len(data)),
273
+ "{:,d}".format(state.totalSent),
274
+ )
275
+ )
276
+
277
+ # Wait for all the sending to complete
278
+ yield state.dataQueueEmptyDeferred
279
+
280
+ print(
281
+ "%s messages were out of order, the most out of order was %s"
282
+ % (state.totalMessagesOutOfOrder, state.highestOutOfOrderIndex)
283
+ )
284
+
285
+ print(
286
+ "Sent %s from the vortex client"
287
+ % "{:,d}".format(state.totalSentFromClient)
288
+ )
289
+
290
+ print(
291
+ "Sent %s from the vortex server"
292
+ % "{:,d}".format(state.totalSentFromServer)
293
+ )
294
+
295
+ print(
296
+ "Data : count %s, total size %s, max size %s, min size %s, average %s"
297
+ % (
298
+ state.totalMessagesSent,
299
+ "{:,d}".format(state.totalSent),
300
+ "{:,d}".format(max(state.dataSizeStats)),
301
+ "{:,d}".format(min(state.dataSizeStats)),
302
+ "{:,d}".format(int(state.totalSent / state.totalMessagesSent)),
303
+ )
304
+ )
305
+
306
+ totalVortexMsgs = sum(state.vortexSizeStats)
307
+ print(
308
+ "VortexMsg: count %s, total size %s, max size %s, min size %s, average %s"
309
+ % (
310
+ state.totalMessagesSent,
311
+ "{:,d}".format(totalVortexMsgs),
312
+ "{:,d}".format(max(state.vortexSizeStats)),
313
+ "{:,d}".format(min(state.vortexSizeStats)),
314
+ "{:,d}".format(int(totalVortexMsgs / state.totalMessagesSent)),
315
+ )
316
+ )
317
+
318
+ # Run our checks
319
+ self.assertEqual(state.totalSent, state.totalReceived)
320
+ self.assertFalse(len(state.dataQueue))
321
+
322
+ # Cleanup
323
+ endpoint.shutdown()
324
+ del checker
325
+ del state
326
+ del endpoint
327
+
328
+ gc.collect()
329
+
330
+
331
+ class VortexTcpConnectTest(
332
+ unittest.TestCase,
333
+ MemoryCheckerTestMixin,
334
+ VortexTcpConnectTestMixin,
335
+ VortexSendReceiveTestMixin,
336
+ ):
337
+ @inlineCallbacks
338
+ def __vortexReconnect(self, count):
339
+ self._memMark()
340
+ for x in range(count):
341
+ print("Reconnecting #%s" % x)
342
+ yield self._connect()
343
+ self._disconnect()
344
+ self._memPrintIncrease()
345
+ self._memPrintIncrease()
346
+
347
+ @inlineCallbacks
348
+ def test_vortexReconnect100(self):
349
+ yield self.__vortexReconnect(100)
350
+
351
+ @inlineCallbacks
352
+ def __vortexReconnect_with_data(self, count):
353
+ self._memMark()
354
+ for x in range(count):
355
+ print("Reconnecting #%s" % x)
356
+ yield self._connect()
357
+ yield self._vortexTestTcpServerClient(
358
+ totalMessagesToSend=10, exactMessageSizeBytes=100 * 1024
359
+ )
360
+ self._disconnect()
361
+ self._memPrintIncrease()
362
+ self._memPrintIncrease()
363
+
364
+ @inlineCallbacks
365
+ def test_vortexReconnect100_with_data(self):
366
+ yield self.__vortexReconnect_with_data(100)
367
+
368
+
369
+ class VortexTcpMemoryLeakTest(
370
+ unittest.TestCase,
371
+ MemoryCheckerTestMixin,
372
+ VortexTcpConnectTestMixin,
373
+ VortexSendReceiveTestMixin,
374
+ ):
375
+ @inlineCallbacks
376
+ def __vortexSendMsgCountMsgSize(self, count, size, compression=9):
377
+ self._memMark()
378
+ yield self._connect()
379
+ yield self._vortexTestTcpServerClient(
380
+ totalMessagesToSend=count,
381
+ printStatusEveryXMessage=1000,
382
+ exactMessageSizeBytes=size,
383
+ payloadCompression=compression,
384
+ )
385
+ self._disconnect()
386
+ self._memPrintIncrease()
387
+
388
+ @inlineCallbacks
389
+ def test_1vortexSend1_1kb_compression1(self):
390
+ yield self.__vortexSendMsgCountMsgSize(1, 1 * 1024, 1)
391
+
392
+ @inlineCallbacks
393
+ def test_1vortexSend1_300kb_compression1(self):
394
+ yield self.__vortexSendMsgCountMsgSize(1, 300 * 1024, 1)
395
+
396
+ @inlineCallbacks
397
+ def test_1vortexSend10000_1kb_compression1(self):
398
+ yield self.__vortexSendMsgCountMsgSize(10000, 1 * 1024, 1)
399
+
400
+ @inlineCallbacks
401
+ def test_1vortexSend10000_100kb_compression1(self):
402
+ yield self.__vortexSendMsgCountMsgSize(10000, 100 * 1024, 1)
403
+
404
+ @inlineCallbacks
405
+ def test_1vortexSend10000_1kb_compression9(self):
406
+ yield self.__vortexSendMsgCountMsgSize(10000, 1 * 1024, 9)
407
+
408
+ @inlineCallbacks
409
+ def test_1vortexSend10000_100kb_compression9(self):
410
+ yield self.__vortexSendMsgCountMsgSize(10000, 100 * 1024, 9)
411
+
412
+ @inlineCallbacks
413
+ def __vortexSendTotalSendMsgSize(
414
+ self, totalSend, msgSize, compression=9, fromServer=False
415
+ ):
416
+ self._memMark()
417
+ yield self._connect()
418
+ yield self._vortexTestTcpServerClient(
419
+ totalBytesToSend=totalSend,
420
+ printStatusEveryXMessage=1000,
421
+ maxMessageSizeBytes=msgSize,
422
+ sendFromServerOnly=fromServer,
423
+ payloadCompression=compression,
424
+ )
425
+ self._disconnect()
426
+ self._memPrintIncrease()
427
+
428
+ @inlineCallbacks
429
+ def test_2vortexSend1mb_1kb(self):
430
+ yield self.__vortexSendTotalSendMsgSize(1024 ** 2, 1 * 1024)
431
+
432
+ @inlineCallbacks
433
+ def test_2vortexSend1mb_100kb(self):
434
+ yield self.__vortexSendTotalSendMsgSize(1024 ** 2, 100 * 1024)
435
+
436
+ @inlineCallbacks
437
+ def test_3vortexSend1mb_X10_yes_reconnect(self):
438
+ mem = MemoryCheckerTestMixin()
439
+ mem._memMark()
440
+
441
+ print(" ===== START LOOP ===== ")
442
+ for i in range(10):
443
+ print(" ===== Running iteration %s ===== " % i)
444
+ self._memMark()
445
+ yield self._connect()
446
+ yield self._vortexTestTcpServerClient(
447
+ totalBytesToSend=1024 ** 2,
448
+ printStatusEveryXMessage=1000,
449
+ maxMessageSizeBytes=100 * 1024,
450
+ )
451
+ self._disconnect()
452
+ self._memPrintIncrease()
453
+
454
+ print(" ===== END LOOP ===== ")
455
+ mem._memPrintIncrease()
456
+
457
+ @inlineCallbacks
458
+ def test_3vortexSend1mb_X10_no_reconnect(self):
459
+ mem = MemoryCheckerTestMixin()
460
+ mem._memMark()
461
+ # Initialise the vortex
462
+ yield self._connect()
463
+
464
+ print(" ===== START LOOP ===== ")
465
+ for i in range(10):
466
+ print(" ===== Running iteration %s ===== " % i)
467
+ # Setup the parameters for the test
468
+ self._memMark()
469
+ yield self._vortexTestTcpServerClient(
470
+ totalBytesToSend=1024 ** 2,
471
+ printStatusEveryXMessage=1000,
472
+ maxMessageSizeBytes=1 * 1024,
473
+ )
474
+ self._memPrintIncrease()
475
+
476
+ self._disconnect()
477
+ print(" ===== END LOOP ===== ")
478
+ mem._memPrintIncrease()
479
+
480
+ @inlineCallbacks
481
+ def test_4vortexSend10mb(self):
482
+ yield self.__vortexSendTotalSendMsgSize(1024 ** 2 * 10, 100 * 1024)
483
+
484
+ @inlineCallbacks
485
+ def test_5vortexSend100mb(self):
486
+ yield self.__vortexSendTotalSendMsgSize(1024 ** 2 * 100, 1024 ** 2)
487
+
488
+ @inlineCallbacks
489
+ def test_6vortexSend500mb(self):
490
+ yield self.__vortexSendTotalSendMsgSize(1024 ** 2 * 500, 1024 ** 2)
491
+
492
+
493
+ class VortexTcpMemoryLeakLargeMessagesTest(
494
+ unittest.TestCase,
495
+ MemoryCheckerTestMixin,
496
+ VortexTcpConnectTestMixin,
497
+ VortexSendReceiveTestMixin,
498
+ ):
499
+ # Increase the timeout to 15 minutes
500
+ timeout = 30 * 60
501
+
502
+ _patchedProcessData_dataReceivedLen = 0
503
+
504
+ def _processData_patch(self):
505
+ VortexTcpMemoryLeakLargeMessagesTest._patchedProcessData_dataReceivedLen += len(
506
+ self._data
507
+ )
508
+
509
+ # Just drop the data and continue
510
+ self._data = b""
511
+
512
+ @inlineCallbacks
513
+ def __vortexSend1g_oneway_maxmsg(self, msgSize, totalSize=1024 ** 2 * 500):
514
+ tracemalloc.start(5)
515
+ self._memMark()
516
+ yield self._connect()
517
+ yield self._vortexTestTcpServerClient(
518
+ totalBytesToSend=totalSize,
519
+ printStatusEveryXMessage=1000,
520
+ exactMessageSizeBytes=msgSize,
521
+ sendFromServerOnly=True,
522
+ payloadCompression=0,
523
+ )
524
+
525
+ self._disconnect()
526
+
527
+ snapshot = tracemalloc.take_snapshot()
528
+ top_stats = snapshot.statistics("lineno")
529
+
530
+ print("[ Top 10 ]")
531
+ for stat in top_stats[:10]:
532
+ print(stat)
533
+
534
+ tracemalloc.stop()
535
+
536
+ for _ in range(5):
537
+ d = Deferred()
538
+ reactor.callLater(2, d.callback, True)
539
+ print("Sleeping 2 seconds")
540
+ yield d
541
+ self._memPrintIncrease()
542
+
543
+ @inlineCallbacks
544
+ def test_1vortexSend50mb_oneway_msg10kb(self):
545
+ yield self.__vortexSend1g_oneway_maxmsg(
546
+ 10 * 1024, totalSize=1024 ** 2 * 50
547
+ )
548
+
549
+ @inlineCallbacks
550
+ def test_1vortexSend50mb_oneway_msg100kb(self):
551
+ yield self.__vortexSend1g_oneway_maxmsg(
552
+ 100 * 1024, totalSize=1024 ** 2 * 50
553
+ )
554
+
555
+ @inlineCallbacks
556
+ def test_1vortexSend50mb_oneway_msg1mb(self):
557
+ yield self.__vortexSend1g_oneway_maxmsg(
558
+ 1 * 1024 ** 2, totalSize=1024 ** 2 * 50
559
+ )
560
+
561
+ @inlineCallbacks
562
+ def test_1vortexSend50mb_oneway_msg3mb(self):
563
+ yield self.__vortexSend1g_oneway_maxmsg(
564
+ 3 * 1024 ** 2, totalSize=1024 ** 2 * 50
565
+ )
566
+
567
+ @inlineCallbacks
568
+ def test_1vortexSend50mb_oneway_msg10mb(self):
569
+ yield self.__vortexSend1g_oneway_maxmsg(
570
+ 10 * 1024 ** 2, totalSize=1024 ** 2 * 50
571
+ )
572
+
573
+ @inlineCallbacks
574
+ def test_1vortexSend50mb_oneway_msg50mb(self):
575
+ yield self.__vortexSend1g_oneway_maxmsg(
576
+ 50 * 1024 ** 2, totalSize=1024 ** 2 * 50
577
+ )
578
+
579
+ @inlineCallbacks
580
+ def test_1vortexSend500mb_oneway_msg10mb(self):
581
+ yield self.__vortexSend1g_oneway_maxmsg(
582
+ 10 * 1024 ** 2, totalSize=500 * 1024 ** 2
583
+ )
584
+
585
+
586
+ class VortexTcpMemoryLeakLargeTransfersTest(
587
+ unittest.TestCase,
588
+ MemoryCheckerTestMixin,
589
+ VortexTcpConnectTestMixin,
590
+ VortexSendReceiveTestMixin,
591
+ ):
592
+ @inlineCallbacks
593
+ def __vortexSendTest(self, total, compression):
594
+ self._memMark()
595
+ yield self._connect()
596
+ yield self._vortexTestTcpServerClient(
597
+ totalBytesToSend=total,
598
+ printStatusEveryXMessage=10000,
599
+ maxMessageSizeBytes=10 * 1024 ** 2,
600
+ payloadCompression=compression,
601
+ )
602
+ self._disconnect()
603
+ self._memPrintIncrease()
604
+
605
+ @inlineCallbacks
606
+ def test_2vortexSend1gb_compression1(self):
607
+ yield self.__vortexSendTest(1024 ** 3, compression=1)
608
+
609
+ @inlineCallbacks
610
+ def test_3vortexSend3gb_compression1(self):
611
+ yield self.__vortexSendTest(1024 ** 3 * 3, compression=1)
@@ -0,0 +1,87 @@
1
+ """
2
+ * Created by Synerty Pty Ltd
3
+ *
4
+ * This software is open source, the MIT license applies.
5
+ *
6
+ * Website : http://www.synerty.com
7
+ * Support : support@synerty.com
8
+ """
9
+ import tracemalloc
10
+
11
+ from twisted.internet import reactor
12
+ from twisted.internet.defer import inlineCallbacks, Deferred
13
+ from twisted.trial import unittest
14
+
15
+ from vortex.VortexTcpMemoryLeakPayloadTest import (
16
+ MemoryCheckerTestMixin,
17
+ VortexTcpConnectTestMixin,
18
+ )
19
+
20
+
21
+ class VortexTcpMemoryLeakRawTest(
22
+ unittest.TestCase, MemoryCheckerTestMixin, VortexTcpConnectTestMixin
23
+ ):
24
+ # Increase the timeout to 15 minutes
25
+ timeout = 30 * 60
26
+
27
+ _patchedProcessData_dataReceivedLen = 0
28
+
29
+ def _processData_patch(self):
30
+ VortexTcpMemoryLeakRawTest._patchedProcessData_dataReceivedLen += len(
31
+ self._data
32
+ )
33
+
34
+ # Just drop the data and continue
35
+ self._data = b""
36
+
37
+ @inlineCallbacks
38
+ def test_1vortexSend50mb_oneway_msg1mb_client_drop_data(self):
39
+ tracemalloc.start(5)
40
+ yield self._connect()
41
+
42
+ self._memMark()
43
+
44
+ from vortex.VortexPayloadProtocol import VortexPayloadProtocol
45
+
46
+ VortexPayloadProtocol._processData = (
47
+ VortexTcpMemoryLeakRawTest._processData_patch
48
+ )
49
+
50
+ dataSent = 0
51
+ for _ in range(1024):
52
+ dataSent += 1024**2
53
+ self._vortexServer.sendVortexMsg(b"x" * 1024**2)
54
+
55
+ # while dataSent < self._patchedProcessData_dataReceivedLen:
56
+ for _ in range(2):
57
+ print(
58
+ "Sleeping 2 seconds, send %s vs received %s"
59
+ % (dataSent, self._patchedProcessData_dataReceivedLen)
60
+ )
61
+
62
+ d = Deferred()
63
+ reactor.callLater(2, d.callback, True)
64
+ yield d
65
+ self._memPrintIncrease()
66
+
67
+ snapshot = tracemalloc.take_snapshot()
68
+ top_stats = snapshot.statistics("lineno")
69
+
70
+ print("[ Top 10 ]")
71
+ for stat in top_stats[:10]:
72
+ print(stat)
73
+
74
+ tracemalloc.stop()
75
+
76
+ # while dataSent < self._patchedProcessData_dataReceivedLen:
77
+ for _ in range(2):
78
+ print("Sleeping 2 seconds")
79
+
80
+ d = Deferred()
81
+ reactor.callLater(2, d.callback, True)
82
+ yield d
83
+ self._memPrintIncrease()
84
+
85
+ self._memPrintIncrease()
86
+
87
+ self._disconnect()