473,227 Members | 1,582 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,227 software developers and data experts.

ArrayList in Thread question

I am using VB.NET 2003 and a socket control to receive and sending data to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class
Jan 6 '07 #1
6 3106
Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microsof t.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:
>I am using VB.NET 2003 and a socket control to receive and sending data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class

Jan 6 '07 #2
fniles,

Here the documentation is using the term "collection" to refer to all
collections, including arraylist collections.

Kerry Moorman
"fniles" wrote:
Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microsof t.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:
I am using VB.NET 2003 and a socket control to receive and sending data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class


Jan 6 '07 #3
THanks.
To guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:AE**********************************@microsof t.com...
fniles,

Here the documentation is using the term "collection" to refer to all
collections, including arraylist collections.

Kerry Moorman
"fniles" wrote:
>Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it
will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microso ft.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe
for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an
exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:

I am using VB.NET 2003 and a socket control to receive and sending
data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain
at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf
ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class



Jan 6 '07 #4
On 2007-01-06, fniles <fn****@pfmail.comwrote:
THanks.
>To guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?
There are a lot of issues with threading and collections. You have to be very
careful - even with a syncronized wrapper. The fact, is that lots of stuff
can happen in a multi-threaded program in orders that you do not intend.. for
example:

sub somesub ' run on a thread
arraylist.clear ()
end sub
function acoolfunction 'run on a different thread
if arraylist.count 0
return arraylist(0)
end if
end function

hmmm, this is a syncronized collection, but the problem is that it is only
syncronized between calls to it's methods - so what happens if you get this
order of execution:

'arraylist starts with count 10
function acoolfunction
if arraylist.count 0

---- Task switch

sub somesub
arraylist.clear()

--- Task Switch

return arraylist(0) ' BIG FAT EXCEPTION

See, in these kinds of operations, you really need something like an sql
transaction - to treat multiple operations as atomic. You achieve that using
the synclock statement (or some other locking mechanism, such as
system.threading.monitor). This is refered to as a "critical section". Then
the code would look something like:

sub somesub ' run on a thread
synclock arraylist.syncroot
arraylist.clear()
end synclock
end sub

function acoolfunction ' run on a different thread
synclock arraylist.syncroot ' lock the arraylist
if arraylist.count 0
return arraylist(0)
endif
end synclock
end function

Now those blocks of code can not be entered at the same time... This makes
sure that the execution scenario from my example does not occur. All requests
will be queued, until the end of the synclock block... Make sense? Also, be
aware that the object you lock on needs to be the same for all the sync'd
operations and it must be a reference type. You can pass in a value, type and
you won't get a compiler error - you code just won't be thread safe. This is
because synclock expects the sync object to be of type object - if you pass in
say an integer value, then it will be boxed - but the object wrapper will be
different in each block of code.

I find most of the operations I do are like the above and involve multiple calls
to the collection, so I very seldom use the syncronized wrapper - that just
adds extra locking overhead for every call. So, I tend to use code similar to
the above, which does basically the same thing except over mutlipe calls.

Watch out for deadlocks, etc. Multi-threaded code is very hard to get right,
so be prepared for problems :) I have done quite a bit of multi-threaded code
over the last couple of years - and I still don't feel I'm anywhere near an
expert at it...

--
Tom Shelton
Jan 6 '07 #5
Thank you very much for your reply.

I have a few more questions.
1. In your example using the synclock statement, did you mean that you use
arraylist and not the syncronized arraylist with the synclock ?
2. >Also, be aware that the object you lock on needs to be the same for all
the sync'd operations and it must be a reference type.
In my program I did not pass in the parameter. The arraylist and its
syncronized arraylist are in the class like the following:
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)
3. Can I simply trap the exception when it happen like the following ?
sub somesub ' run on a thread
try
arraylist.clear ()
Catch ex As Exception
End Try
end sub

function acoolfunction 'run on a different thread
if arraylist.count 0
try
return arraylist(0)
Catch ex As Exception
End Try
end if
end function

4. What can I do when deadlocks happens ?

"Tom Shelton" <to*********@comcastXXXXXXX.netwrote in message
news:6d******************************@comcast.com. ..
On 2007-01-06, fniles <fn****@pfmail.comwrote:
>THanks.
>>To guarantee thread safety during enumeration, you can either lock
the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?

There are a lot of issues with threading and collections. You have to be
very
careful - even with a syncronized wrapper. The fact, is that lots of
stuff
can happen in a multi-threaded program in orders that you do not intend..
for
example:

sub somesub ' run on a thread
arraylist.clear ()
end sub
function acoolfunction 'run on a different thread
if arraylist.count 0return arraylist(0)
end if
end function

hmmm, this is a syncronized collection, but the problem is that it is only
syncronized between calls to it's methods - so what happens if you get
this
order of execution:

'arraylist starts with count 10
function acoolfunction
if arraylist.count 0

---- Task switch

sub somesub
arraylist.clear()

--- Task Switch

return arraylist(0) ' BIG FAT EXCEPTION

See, in these kinds of operations, you really need something like an sql
transaction - to treat multiple operations as atomic. You achieve that
using
the synclock statement (or some other locking mechanism, such as
system.threading.monitor). This is refered to as a "critical section".
Then
the code would look something like:

sub somesub ' run on a thread
synclock arraylist.syncroot
arraylist.clear()
end synclock
end sub

function acoolfunction ' run on a different thread
synclock arraylist.syncroot ' lock the arraylist
if arraylist.count 0
return arraylist(0)
endif
end synclock
end function

Now those blocks of code can not be entered at the same time... This
makes
sure that the execution scenario from my example does not occur. All
requests
will be queued, until the end of the synclock block... Make sense? Also,
be
aware that the object you lock on needs to be the same for all the sync'd
operations and it must be a reference type. You can pass in a value, type
and
you won't get a compiler error - you code just won't be thread safe. This
is
because synclock expects the sync object to be of type object - if you
pass in
say an integer value, then it will be boxed - but the object wrapper will
be
different in each block of code.

I find most of the operations I do are like the above and involve multiple
calls
to the collection, so I very seldom use the syncronized wrapper - that
just
adds extra locking overhead for every call. So, I tend to use code
similar to
the above, which does basically the same thing except over mutlipe calls.

Watch out for deadlocks, etc. Multi-threaded code is very hard to get
right,
so be prepared for problems :) I have done quite a bit of multi-threaded
code
over the last couple of years - and I still don't feel I'm anywhere near
an
expert at it...

--
Tom Shelton

Jan 7 '07 #6
On 2007-01-07, fniles <fn****@pfmail.comwrote:
Thank you very much for your reply.

I have a few more questions.
1. In your example using the synclock statement, did you mean that you use
arraylist and not the syncronized arraylist with the synclock ?
I generally don't use a sync'd arraylist. Simply because it is rare that I
use atomic operations, generally I want to do stuff like in my acoolfunction -
do a test and an operation. The sync'd arraylist won't do anything for you in
these cases - except add the extra locking overhead. So, I generally just use
the arraylist with it's syncroot property.
2. >Also, be aware that the object you lock on needs to be the same for all
the sync'd operations and it must be a reference type.
In my program I did not pass in the parameter. The arraylist and its
syncronized arraylist are in the class like the following:
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)
That's fine. My code was psuedo code. So, in your case:

SyncLock Me.Quotes.SyncRoot
' do cool stuff with quotes
End SyncLock

You just need to make sure that all the methods you are syncronizing are using
the same reference.
3. Can I simply trap the exception when it happen like the following ?
sub somesub ' run on a thread
try
arraylist.clear ()
Catch ex As Exception
End Try
end sub

function acoolfunction 'run on a different thread
if arraylist.count 0
try
return arraylist(0)
Catch ex As Exception
End Try
end if
end function
Sure. You could trap the exception. The point of the example was to show
what might happen... You just need to be aware that in a multi-threaded
application you can not be sure of your order of execution - so in some cases
you need to introduce locking to ensure that bad things don't happen.
4. What can I do when deadlocks happens ?
Not a lot :) The thing to do with deadlocks is to make sure they don't
happen. There are lots of techniques on the web for doing so. One is using a
timed lock. There is a discussion of this technique at:

http://www.interact-sw.co.uk/iangblo.../03/23/locking

The code is C#, but this would apply in VB.NET as well.

There are other techniques for prevention and detection of deadlocks - but
that is a very advanced topic. One that I myself am still exploring. Like I
said, I'm far from an expert on this topic - even though I've done lots of it
over the last two to three years :)

--
Tom Shelton
Jan 7 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: jarkkotv | last post by:
Hi everyone! I'm having a little problem when sorting the ArrayList and I was wondering if there is a .NET guru who can help me out :) I'm trying to sort ArrayList alphabetically in ASP.Net...
10
by: Eric | last post by:
I'm looking at this page in the MSDN right here: ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist classsynchronizedtopic2.htm (or online here:...
7
by: ORC | last post by:
Hi, How to create an ArrayList from a System.Array or inserting the System.Array into the ArrayList ? Thanks Ole
5
by: Zeng | last post by:
Hello Everyone, Is there anything wrong with this block of code? ArrayList arr = new ArrayList( 33 ); for( int i = 0; i < 33; ++i ) { arr.Insert( i, new MyObject() ); }
14
by: Mike | last post by:
I had a question about threading and access to private class variables. I am developing a windows service which has a class inside of it which will receive various asynchronous calls to it via...
1
by: KK | last post by:
Dear All I have a class whose methods are getting called from multiple threads in my application. For example class DataDistribution { private ArrayList datset; public DataDistribution() {...
3
by: Ryan Liu | last post by:
Hi, What does ArrayList.Synchronized really do for an ArrayList? Is that equal to add lock(this) for all its public methods and properties? Not just for Add()/Insert()/Remvoe()/Count, but also...
28
by: wanwan | last post by:
I wrote a class and have objects from this class added to an arraylist. When I retrieve the objects from the arraylist, should I use ctype or directcast to cast them back to the original class.?
4
by: archana | last post by:
Hi all, I am having one arraylist which i want to share accross threads. What i am doing is traversing through element of arraylist in both the thread. Means just reading element of that...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.