|
Luc Pattyn wrote:
I am under the impression your code generates way too many exceptions, and that's what
is slowing things down; optimizing with ranges wont make much of a difference as long
as Paint and MouseMove events generate one or more PointNotVisible events.
Yeah, it does generate too many exceptions.
The ranges are not only to improve performance of the core functionality but it is also to greatly reduce memory consumption. Selecting 1 million bytes will not use a ton of memory any more, it will use 2 longs for each selection (plus another long if you count the range variable in the Range struct).
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
Have you looked at version 2.0 yet?
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
I am getting build errors with HDPC2.0:
2 warnings in Range.cs
and 8 errors in Data.cs; first is:
Error 3 The name 'end' does not exist in the current context H:\...\HDPC\HDPC\Data.cs 235 25 HDPC
If you want me to have a look at 2.0 please provide a zip that builds.
BTW I did not recognize any of the things I looked at in 1.0, seems filenames and code
have changed drastically.
Greetings,
Luc Pattyn
|
|
|
|
|
Comment out Range[] ReturnIndexRanges(long[] indexes), that was the method I was working on when I first posted here about the treads.
Luc Pattyn wrote:
BTW I did not recognize any of the things I looked at in 1.0, seems filenames and code
have changed drastically.
Yes they have and much of it will be different. The public API will be mostly the same though with some additions and maybe slight modifications.
You are looking at the Data class which is the core of HDPC. It does not expose any methods to the programmer as it is internal. It is used by HDPC. I will email you a diagram of the architecture of version 2.0.
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
I am now looking at Data.cs in HDPC1.0 and HDPC2.0 in parallel.
Switching _selected and _changed from <int> collections to <range> collections is
definitely a big step in the right direction.
I am sure working with ranges EVRYWHERE will really speed things up.
To facilitate thiseven more, I would suggest to introduce a new class RangeCollection,
which somehow holds any number of non-overlapping ranges (maybe ordered, maybe not,
thats up to your judgement). The class would offer methods such as:
- Clear()
- AddRange(start, length) or (Range)
- RemoveRange(start, length) or (Range)
- GetEnumerator()
There would be no restrictions on AddRange; you must choose some details:
- when adjacent to an existing range, merge or not ? (may even cause a double merge)
- when overlapping, ignore the overlap or throw Exception ?
There would be no restrictions on RemoveRange (it may modify more than one of the
internally held ranges). You must choose the spec when it contains items not currently
represented in the range list (probably an Exception).
The Enumerator would return a collection of ranges that are logically equal to
what was added/removed before, without having to be identical...
In this way, the rest of your app can easily be range oriented, and the RangeCollection
class is not that difficult to create either.
If handled in this way, you may not need an "indexesArray to rangesArray" conversion at all,
or if you do (e.g. for API compatibility), its performance might be of lesser importance.
One final remark: your current Data class is not really thread-safe, and
the RangeCollection class would not be either, so it is not obvious for either of them
how to switch to a multi-threading approach (assuming you would still be
considering that at all; I dont expect it will come to that).
Regards,
Luc Pattyn
|
|
|
|
|
Luc Pattyn wrote: I would suggest to introduce a new class RangeCollection
That is a good idea. That will keep things organized at the very least.
Luc Pattyn wrote: when adjacent to an existing range, merge or not ? (may even cause a double merge)
Just as in the SelectData method ranges are joined even if they are adjacent but not overlapping.
Luc Pattyn wrote: when overlapping, ignore the overlap or throw Exception ?
When overlapping the range being overlapped may be extended or the new range being added may just be ignored as it will not be needed(if it is inside a range [.[...]....])
Luc Pattyn wrote: You must choose the spec when it contains items not currently
represented in the range list (probably an Exception).
If you remove a range that extends beyond any other range or does not even exist then it will do nothing or modify existing ranges.
Luc Pattyn wrote: If handled in this way, you may not need an "indexesArray to rangesArray" conversion at all,
or if you do (e.g. for API compatibility), its performance might be of lesser importance.
In HDPC 2.0 it wont be needed because it will be range orientated, even without the RangeCollection class available. I will keep the index - range conversions because they may be needed for some unforeseen reason. However it is unlikely I will ever use it in my own code.
Threads are beyond my knowledge for now so it will be single threaded. I'm making HDPC 2.0 capable of handling extremely large chucks of data and files. I doubt the CPU will be a bottleneck in this case. Besides thread creation creates additional overhead.
Thanks for all your help.
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
You're welcome.
I think it's time now to change the thread's title.
Luc Pattyn
|
|
|
|
|
I forgot one question: what is the source of your array ?
I mean, if there already is something that performs the task
of ordering a lot of numbers and then putting them in an array, seems like
your range-finding requirement performance-wise should be integrated with it !
I would even claim:
if you are handed a lot of numbers one by one, in random order, then
solving the overall task would work faster AND be easier than doing
it in two phases.
Furthermore, it does resemble memory recombination in a dynamic memory
manager, doesnt it ?
And if that is what it is, then there are even better ways of doing it
(taking advantage of the memory it describes !)
Luc Pattyn
|
|
|
|
|
Hey guys,
the page is wonderful, but I've got a problem with C# .NET! I wanna do some Clipboard things in a Timer, but it will not work because of the MTA Mode and I have no clue how to set it to STA Mode.
Pls help me!!!
|
|
|
|
|
Add the [STAThread] attribute above your Main method. The main method will most likely be in the static class Program inside of the Program.cs file.
namespace YourProgram
{
class Program
{
[STAThread]
static void Main()
{
}
}
}
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
Well I do recall some adventures we once had around the STA/MTA stuff.
We started of in STA (isnt that the default?) and had to switch to MTA to
achieve a sufficient level of parallellism.
So what I'm telling you is turning MTA down to STA, while solving one problem,
may introduce new problems performance wise. It just seems wrong to me that
there is such a global decision to make... or maybe I never sufficiently
understood it all in the first place.
Luc Pattyn
|
|
|
|
|
I think you didn't understand me!
My main Thread is in STA! It is like you say!
But when I start a Timer, it makes a new Thread and a new thread is not the main thread, so it is in MTA Mode and there is no way to turn it to STA!!!!
Just try this:
make a little Form with just one button, which starts with a Timer this function:
private void TimerProc()
{
Clipboard.SetText("test text");
}
It won't work, because the Timer thread is in MTA Mode and the Clipboard class need to be used in a STAThread!!!
|
|
|
|
|
new_era88 wrote: It won't work, because the Timer thread is in MTA Mode and the Clipboard class need to be used in a STAThread!!!
Are you using the
System.Threading.Timer
System.Timers.Timer or the
System.Windows.Forms.Timer?
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
Just like the title says, I use System.Timers.Timer!
The SetAppartmentState() Method exists just for Threads, but not for a Timer!
When I use a
while(true)
{
dosomething();
Thread.Sleep(1000);
}
my whole windows get stuck for a while and I don't know why!
nevertheless thanks for your help!
|
|
|
|
|
Use the System.Windows.Timer, I tried it and it works. Text gets set to the clipboard and when I get it out it is the text I put in.
Also the [STAThread] attribute is set (it is default for WinForms apps) just in case it is not currently set to that in your project.
█▒▒▒▒▒██▒█▒██
█▒█████▒▒▒▒▒█
█▒██████▒█▒██
█▒█████▒▒▒▒▒█
█▒▒▒▒▒██▒█▒██
|
|
|
|
|
Yes!!!!!!!!!!
You are my Hero!!!!
It works!!!!
Thank you and thanks to all of you who tried me to help!
|
|
|
|
|
You can create a new thread and let it sleep for a while:
Thread thd = new Thread(new ThreadStart(runTimer));<br />
<br />
thd.Start();<br />
<br />
void runTimer(){<br />
while(true) {<br />
Console.WriteLine("Timer fired");<br />
Thread.Sleep(1000);<br />
}<br />
}
You can change the threadmodel of a thread to STA, while keeping the rest in MTA model.
See this MSDN article: http://msdn2.microsoft.com/en-us/library/system.threading.thread.apartmentstate.aspx[^]
Hope this helps a bit to get you going in the right direction.
WM.
What about weapons of mass-construction?
"You can always try to smash it with a wrench to fix that. It might actually work" - WillemM
|
|
|
|
|
Yes, I remember now.
You CAN set the MTA/STA for each thread individually,
use Thread.AppartMentState on 1.1
or Thread.SetAppartMentState on 2.0
but you can set it only once for any particular thread !
Luc Pattyn
|
|
|
|
|
Hi there.
I'm writing a hash file converter to convert a set of file hashes from one vendors format to another.
As input I have a 32 byte long string containing a hash value stored in a byte[32] array:
6A87A34023132CF8F6D7FDFFB269E3FA
I want to convert this into a 16 byte value such that the hex representation is the same, ie:
byte[16] = {0x6A,0x87,0xA3 ... }.
I hope this makes sense, I'm really struggling with this as my binary skills are not so sharp...
Any assistance woud be greatly appreciated.
Kind regards,
John.
|
|
|
|
|
No, it doesn't really make sense...
What is a "32 byte long string"? A string consists of characters, not bytes. It looks like you have a string containing 32 characters, but that will occupy 64 bytes.
Have you really stored the string in a byte[32] array? How? Have you encoded the string? Then you should decode the string using the same encoding.
Once you have the data as a string, you can split it up into 16 separate strings using the Substring method. Then use the Int32.Parse method with NumberStyles.AllowHexSpecifier to parse each two character string into a byte value.
---
Year happy = new Year(2007);
|
|
|
|
|
Yup, you're right - it's a 32 character long string, however it does only occupy 32 bytes - it's not unicode. No encoding required - it's pure ASCII and is stored as such.
Anyway after much head scratching, I've got the following code to work:
// sHash[32] is a byte array length 32
// eg: the hex value 'A6' is split into sHash[0] & sHash[1]
// the following code will amalgamate this character data into a
// byte array length 16
int l = 0, iFirst, iSecond;
for (int k = 0; k < 32; k += 2)
{
if (sHash[k] > '9')
iFirst = (sHash[k] - 'A') + 10;
else
iFirst = (sHash[k] - '0');
if (sHash[k+1] > '9')
iSecond = (sHash[k+1] - 'A') + 10;
else
iSecond = (sHash[k+1] - '0');
EnHash[l++] = Convert.ToByte(((iFirst * 16) + iSecond));
}
Thanks for your comments above - it's an interesting idea to use int32.parse - I'll give that a go just to see how that works - ultimately it's not too diferent from what I worked out.
Kind regards,
John.
|
|
|
|
|
You did it the hard way, you could use System.Globalization.NumberStyles
example:
int i=int.Parse("12",NumberStyles.AllowHexSpecifier);
sets i to 18 (or 0x12).
So you simply could pass a two-char substring to byte.Parse and reduce your
for-loop body to a single statement.
Luc Pattyn
|
|
|
|
|
That's very cool Luc, thank you.
I think I'll implement that as I guess it will make the program run much faster!
Kind regards,
John.
|
|
|
|
|
Okay, having implemented your code I've got a saving of three seconds with 2755 hashes processed.
My code took 2 mins 33 secs to process, whereas yours took 2 minutes 30 - that's 18.3 hash conversions per second! This is a small sample file so I'm sure that in the real world application of this the savings will be very significant.
Many thanks for your help.
Kind regards,
John.
|
|
|
|
|