Picotcp memory usage benchmark (still beta testing)

Dependencies:   PicoTCP lpc1768-picotcp-eth mbed-rtos mbed

This project represents a throughtput test for the EthernetInterface, based on the PicoTCP library.

The purpose of this is to be able to make a comparison of full speed (Rx,Tx and Rx+Tx) and memory between the EthernetInterface based on the lwIP and the one based on PicoTCP .

The benchmark consists of three parts:

  • we are sending 1 Megabyte from the board to host
  • we are waiting for the host to send us 1 Megabyte of data
  • on the last part we are using a TCP Echo Server to send and receive back 1 Megabyte of data

we send/receive 1024 packets of 1024 bytes each and we measure how many bits per second we transmit and receive.

The result:
TX+RX Throughput: 4194304 bytes in 3 seconds (10.457) Mbits/s

Memory report
Current free memory : 19148 bytes
Maximum free memory : 24716 bytes
Minimum free memory : 15476 bytes
Average free memory : 17376 bytes

The python script used

#!/usr/bin/python
import sys, socket
import random, string
import select
from time import time
#ECHO_SERVER_ADDRESS = "10.20.30.139"
ECHO_SERVER_ADDRESS = "192.168.100.12"
ECHO_SERVER_PORT = 7
N_PACKETS = 1024
LEN_PACKET = 1024

TOT_BITS = (LEN_PACKET * N_PACKETS * 8) * 4. # TX bits + RX bits
PACKET = ''.join(random.choice(string.ascii_uppercase+string.digits) for _ in range(LEN_PACKET))
MEGA = 1024 * 1024.
UPDATE_STEP = (N_PACKETS/20) # Make the update step such as one step = 5%
UPDATE_R_STEP = (N_PACKETS/20) #Make the update step such as one step = 1%
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ECHO_SERVER_ADDRESS, ECHO_SERVER_PORT))
start = time()
rx_total = 0
tx_total = 0
data = ''
i = 0
lp = []
p = select.poll()
while(True): # keeping this in for robustness testing, when the test will run for days
	#Stage I - sending data from host towards mbed board	
	print "Started sending data...."
	while (i < N_PACKETS):
	  p.register(s, select.POLLOUT)
	  lp = p.poll(1)
	  if (len(lp) > 0):
	    s.sendall(PACKET)
	    i+=1
	    if (i % UPDATE_STEP) == 0: print "sent %d/%d (%.2f%%)" % (i, N_PACKETS, float(i)/ float(N_PACKETS) * 100.)
	    continue

	#Stage II - receving data from the mbed board
	print "Started receiving data...."
	while(len(data) < N_PACKETS * LEN_PACKET):	
		p.register(s, select.POLLIN)
		lp = p.poll(1)
		if(len(lp) > 0):
		    r = s.recv(LEN_PACKET)
		    if (r != ''):
		      data += r
		      if (len(data) / LEN_PACKET) % UPDATE_R_STEP: print "recvd %d/%d (%.2f%%)" % (len(data)/LEN_PACKET, N_PACKETS, float(len(data))/ float(N_PACKETS * LEN_PACKET) * 100.)
		    else:
		      print "Error receiving !"
		      sys.exit(1)

	#Stage III - echo between host and mbed board
	print "Started echoing data...."
	for i in range(N_PACKETS):
		if (i % UPDATE_STEP) == 0: print "%.2f%%" % (float(i)/float(N_PACKETS) * 100.)
		s.sendall(PACKET)
		data = s.recv(LEN_PACKET)
		if (len(data) != LEN_PACKET):
			print "Error echoing !"
			sys.exit(1)

	print "Test was finished!"
	break;	

t = time() - start
s.close()
print "TX+RX Throughput: %d bytes in %d seconds (%.3f)Mbits/s" % (TOT_BITS / 8, t, ((TOT_BITS / t) / MEGA))

This test is based on the following libraries

Import librarylpc1768-picotcp-eth

A PicoTCP driver for the lpc1768 mbed board

Import libraryPicoTCP

Free (GPLv2) TCP/IP stack developed by TASS Belgium

Import librarymbed-rtos

Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.

Click here to see the results for lwIP

Files at this revision

API Documentation at this revision

Comitter:
tass
Date:
Mon Oct 07 10:43:36 2013 +0000
Parent:
5:7a73a14f5e85
Commit message:
Added new memory and stack measure mechanism.

Changed in this revision

PicoTCP.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
--- a/PicoTCP.lib	Fri Sep 06 10:11:46 2013 +0000
+++ b/PicoTCP.lib	Mon Oct 07 10:43:36 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/daniele/code/PicoTCP/#734099a8df4e
+http://mbed.org/users/daniele/code/PicoTCP/#478be2fd92ac
--- a/main.cpp	Fri Sep 06 10:11:46 2013 +0000
+++ b/main.cpp	Mon Oct 07 10:43:36 2013 +0000
@@ -1,87 +1,55 @@
+/*
+* To enable stack measurement go to pico_mbed.h and add 
+*   #define PICO_MEASURE_STACK
+* to read the current number of free stack words (integers) call stack_get_free_words
+*
+* To enable memory measurement go to pico_mbed.h and add
+*   #define MEMORY_MEASURE
+*/
+
 #include <mbed.h>
 #include <stdarg.h>
 #include "EthernetInterface.h"
 
+extern "C"
+{
+    #include "pico_mbed.h"
+#ifdef MEMORY_MEASURE
+    uint32_t max_mem;
+    uint32_t cur_mem;
+#endif
+}
+
 #define ECHO_SERVER_PORT  7
 #define BUFFER_QUANTITY   (1024*1024)
 
-struct MemoryUsage
-{
-    uint32_t curFreeRam;
-    uint32_t minFreeRam;
-    uint32_t maxFreeRam;
-    uint32_t avgFreeRam;
-    uint32_t stackPointer;
-    uint32_t cntSamples;
-};
+//#define printf(...) do{}while(0)
 
-struct MemoryUsage memoryStats = {0,0xFFFFFFFF,0,0,0};
-
-int fakePrintf(void* pvHeapInfo, char const* pFormatString, ...)
+void printMemoryStats(void)
 {
-    struct MemoryUsage * memStat = (struct MemoryUsage *)pvHeapInfo;
-    static const char* freeRamFormat = "%d bytes in";
-    va_list valist;
-    
-    if(memcmp(pFormatString,freeRamFormat,strlen(freeRamFormat)) == 0)
-    {
-        va_start(valist, pFormatString);
-        unsigned long freeSize = va_arg(valist, unsigned long);
-        memStat->curFreeRam = freeSize;
-        if(memStat->minFreeRam > freeSize)
-            memStat->minFreeRam = freeSize;
-        
-        if(memStat->maxFreeRam < freeSize)
-            memStat->maxFreeRam = freeSize;
-            
-        memStat->avgFreeRam = ((memStat->avgFreeRam * memStat->cntSamples) + freeSize)/(++memStat->cntSamples);
-    }
-    else
-    {
-        // ignore format
-    }
-    return 0;
-}
+#ifdef PICO_MEASURE_STACK
+    printf("******** Stack Statistics\n");
+    printf("Current free stack : %d bytes\n",stack_get_free_words()*sizeof(int));
+    printf("Total stack size : %d bytes\n",STACK_TOTAL_WORDS*sizeof(int));
+    printf("Used : %.2f %%\n",100.0*(float)(STACK_TOTAL_WORDS-stack_get_free_words())/STACK_TOTAL_WORDS);
+#endif
 
-void inline printMemoryStats(void)
-{
-    if(memoryStats.cntSamples == 1)
-        printf("\n\n***** Initial Memory Report *****\n");
-    else
-        printf("\n\n********* Memory Report *********\n");
-    
-    printf("Current free memory : %d bytes\n",memoryStats.curFreeRam);
-    printf("Maximum free memory : %d bytes\n",memoryStats.maxFreeRam);
-    printf("Minimum free memory : %d bytes\n",memoryStats.minFreeRam);
-    printf("Average free memory : %d bytes\n",memoryStats.avgFreeRam);
-    printf("Stack pointer address : %d\n",memoryStats.stackPointer);
-    printf("****************************\n");
-}
-
-void inline memoryStamp(void)
-{
-    __heapstats((__heapprt)fakePrintf, &memoryStats);
-}
-
-void inline stackPtrSnapshot(void)
-{
-    memoryStats.stackPointer = __current_sp();
+#ifdef MEMORY_MEASURE
+    printf("******** Memory Statistics\n");
+    printf("Current used memory : %d bytes\n",cur_mem);
+    printf("Maximum used memory : %d bytes\n",max_mem);
+#endif
 }
 
 int main() {
     
     printf("Ethernet Interface memory test....\n");
     
-    // Initial memory status
-    memoryStamp();
-    stackPtrSnapshot(); // snapshot of the stack pointer before starting benchmark to see the SP.
-    printMemoryStats();
-    
     EthernetInterface eth;
     int connections = 0;
-    //eth.init("192.168.100.12","255.255.255.0","192.168.100.2"); //Use DHCP
     eth.init();
-    eth.connect();
+    printf("Waiting for DHCP to give IP\n");
+    while(eth.connect() != 0);
     printf("IP Address %s\n", eth.getIPAddress());
     
     TCPSocketServer server;
@@ -101,7 +69,6 @@
         int dataReceived = 0;
         int dataSent = 0;
         
-        printf("\n\n\nStarting the receiving part...\n");
         while(dataReceived < BUFFER_QUANTITY)
         {
             int n = client.receive(buffer, sizeof(buffer));
@@ -110,21 +77,15 @@
                 break;
             }
             dataReceived += n;
-            memoryStamp();
         }
         
-       
-        printf("Received : %d bytes\nExpected : %d bytes\n",dataReceived,BUFFER_QUANTITY);
         if(dataReceived < BUFFER_QUANTITY)
         {
             printf("Receiving part of the test has failed. Exiting connection.\n");
+            printf("Received : %d bytes\nExpected : %d bytes\n",dataReceived,BUFFER_QUANTITY);
             break;
         }
-        else{
-            printf("Receiving has passed...\n");
-        }
         
-        printf("\n\n\nStarting the sending part...\n");
         while(dataSent < BUFFER_QUANTITY)
         {
             int n = client.send_all(buffer, sizeof(buffer));
@@ -133,22 +94,16 @@
                 break;
             }
             dataSent += n;
-            memoryStamp();
         }
         
-        printf("Sent : %d bytes\nExpected : %d bytes\n",dataSent,BUFFER_QUANTITY);
         if(dataSent < BUFFER_QUANTITY)
         {
             printf("Sending part of the test has failed. Exiting connection.\n");
+            printf("Sent : %d bytes\nExpected : %d bytes\n",dataSent,BUFFER_QUANTITY);
+
             break;
         }
-        else
-        {
-            printf("Sending test has passed...\n");
-        }
         
-        
-        printf("\n\n\nStarting echo part...\n");
         dataReceived = dataSent = 0;
         while((dataReceived+dataSent) < 2*BUFFER_QUANTITY)
         {
@@ -165,20 +120,17 @@
                 break;
             }
             dataSent += n;
-            memoryStamp();
         }
         
-        printf("Echo size : %d bytes\nExpected : %d bytes\n",(dataReceived+dataSent),2*BUFFER_QUANTITY);
         if((dataReceived+dataSent) < 2*BUFFER_QUANTITY)
         {
+            printf("Echo size : %d bytes\nExpected : %d bytes\n",(dataReceived+dataSent),2*BUFFER_QUANTITY);
             printf("Echo test has failed.Exiting connection...\n");
         }
-        else
-        {
-            printf("Echo test has passed...\n");
-        }
+ 
         break;
      }
+ 
     client.close();
     printf("Test was finished...\n");
     printMemoryStats();
--- a/mbed-rtos.lib	Fri Sep 06 10:11:46 2013 +0000
+++ b/mbed-rtos.lib	Mon Oct 07 10:43:36 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed-rtos/#869ef732a8a2
+http://mbed.org/users/mbed_official/code/mbed-rtos/#ee87e782d34f