-
Posts
91 -
Joined
-
Last visited
-
Days Won
1
Content Type
Forums
Downloads
Forum Articles
Events
Everything posted by Kealper
-
Maps 101: All you need to know about them!
Kealper replied to TheDcoder's topic in AutoIt Technical Discussion
Since it looks like some people were unsure of what I was trying to say in my benchmark, I've edited my post about the benchmark with this clarification: -
Maps 101: All you need to know about them!
Kealper replied to TheDcoder's topic in AutoIt Technical Discussion
I guess you must have read the reply as soon as I had posted it, I changed them over to regular ol' code tags as soon as I had posted it and seen that it didn't like [autoit] ones EDIT: We're just not going to talk about why I edited this. -
Maps 101: All you need to know about them!
Kealper replied to TheDcoder's topic in AutoIt Technical Discussion
The map data type is available in many popular programming languages, and has certain uses that traditional arrays aren't quite as suited-for, especially in an interpreted language such as AutoIt. You can emulate maps using traditional arrays without too much hassle, but in interpreted languages, performance can suffer quite a bit. Comparing the performance of arrays to maps is a bit of an apples-to-oranges comparison, as a traditional array can't do things maps can do. Because of this, I've written a little benchmark that runs on the latest beta version of AutoIt (3.3.15.0 at the time of writing). It uses a 2d array to create a case-sensitive key/value store. If you add data to a key that does not exist, that key is created with the data it was supposed to be assigned. Basically, it's using 2d arrays to create fakes of the new native map type. Native maps can usually handle enormous amounts of key/value pairs and still be very fast at modifying or reading the data in them. AutoIt's new maps are no exception, either! CLARIFICATION: Please understand that this benchmark is NOT comparing the performance of arrays to the performance of maps. The two serve different purposes, and if you put arrays versus maps in a fair benchmark, arrays will be faster. This is true for pretty much any programming language. This benchmark is comparing the methods available for doing a native, dynamically-sized, in-memory key/value store. In the current stable release of AutoIt, the only way to do this without relying on external COM objects (Scripting.Dictionary) is to use a dynamically-sized two-dimensional array. (Or two one-dimensional dynamically-sized arrays, but we'll not get into that as there's not really a good reason to do that over a two-dimensional one.) In the current beta of AutoIt, the map type allows for exactly that, without all of the boilerplate code needed to implement them, as well as a huge speed increase to them since the heavy lifting is being done internally in the interpreter as opposed to being done in AutoIt. One of the key features of this data type is that the amount of things it can store is not a fixed size. This means the more stuff you want to add, the bigger it will grow. The more things you delete from it, the smaller it shrinks. If you need to iterate over a map, it won't have to waste time running through, for example, 9,975 blank entries just to read the 25 populated entries like you would with a 10,000-element fixed-size array. For those saying that this benchmark is not fair to arrays and that there's a more efficient way to do it so they end up doing much better in the benchmark: I know, this isn't meant to be "arrays vs. maps", it's meant to be "fake maps vs. native maps". There's also some optimization that can be done with my FakeMap code, because ReDim is actually pretty slow, but adding that would make the example code harder to read while the end result would still be the same. The benchmark creates a specified number of elements randomly, and sets their values to a random number as well. It then creates one last element and reads that last element's data and prints it into the console. It also prints out the times that each step took, in milliseconds. So, here is the result of these basic benchmarks: 1000+1 elements: Fake map population time (1000 random elements): 1251.122ms Fake map new element 1001 time: 2.022ms Read data: Hello, World! Fake map read element 1001 time: 1.12ms Real map population time (1000 random elements): 2.489ms Real map new element 1001 time: 0.01ms Read data: Hello, World! Real map read element 1001 time: 0.01msSo from here, you can see that with only 1000 elements, the fake map took over 1.2 seconds to create 1000 new elements, 2ms to add the 1001st element, and then another 1ms to read that 1001st element. The native map only took about 2.5ms to create the first 1000 elements, and 0.1ms to create and read the 1001st. Wow! Here's that same benchmark, but instead of 1,000, we'll bump it up to 10,000! Fake map population time (10000 random elements): 123555.641ms Fake map new element 10001 time: 21.328ms Read data: Hello, World! Fake map read element 10001 time: 11.637ms Real map population time (10000 random elements): 27.36ms Real map new element 10001 time: 0.014ms Read data: Hello, World! Real map read element 10001 time: 0.014msTwo minutes for 10,000 new elements in the fake map? Yikes! As you can also see, although the fake map gets exponentially slower with each order of magnitude we go up, the native maps stay fairly consistent still, even at 10,000. At this scale, the amount of time calls to Random() take starts to show. But what if we go further? Let's say... 1,000,000 elements. For obvious reasons, I won't run the fake map code with this many elements, otherwise we'd be here until this time next year waiting for the results... But here is what happens when we have a 1-million-element map, and add one more on to it, then read it back: Real map population time (1000000 random elements): 24357.752ms Real map new element 1000001 time: 0.063ms Read data: Hello, World! Real map read element 1000001 time: 0.029msAs we can see, the two million calls made to Random() certainly did a number on that run time, weighing in at just over 24 seconds. We can safely assume that most of that 24 seconds was spent just generating random numbers because... Adding another element on top of that, then reading it back, is still incredibly fast, given how much data there is, at around 60 microseconds (that's 1/1000th of one millisecond!) to add a new value, and around 30 microseconds to read it back. Even more wow! The code used for this back-of-the-napkin basic benchmark: Global $FakeMap = MapCreate() Global $Map[] Global $t Global $TestSize = 1000 #Region Fake map benchmarking $t = TimerInit() For $i = 1 To $TestSize MapSet($FakeMap, Random(1, 1000000, 1), Random(1, 1000000, 1)) Next ConsoleWrite("Fake map population time (" & $TestSize & " random elements): " & Round(TimerDiff($t), 3) & "ms" & @CRLF) $t = TimerInit() MapSet($FakeMap, "asdf", "Hello, World!") ConsoleWrite("Fake map new element " & ($TestSize + 1) & " time: " & Round(TimerDiff($t), 3) & "ms" & @CRLF) $t = TimerInit() ConsoleWrite("Read data: " & MapRead($FakeMap, "asdf") & @CRLF) ConsoleWrite("Fake map read element " & ($TestSize + 1) & " time: " & Round(TimerDiff($t), 3) & "ms" & @CRLF) #EndRegion #Region Real/native map benchmarking $t = TimerInit() For $i = 1 To $TestSize $Map[Random(1, 1000000, 1)] = Random(1, 1000000, 1) Next ConsoleWrite("Real map population time (" & $TestSize & " random elements): " & Round(TimerDiff($t), 3) & "ms" & @CRLF) $t = TimerInit() $Map["asdf"] = "Hello, World!" ConsoleWrite("Real map new element " & ($TestSize + 1) & " time: " & Round(TimerDiff($t), 3) & "ms" & @CRLF) $t = TimerInit() ConsoleWrite("Read data: " & $Map["asdf"] & @CRLF) ConsoleWrite("Real map read element " & ($TestSize + 1) & " time: " & Round(TimerDiff($t), 3) & "ms" & @CRLF) #EndRegion #Region Wrapper functions to emulate map support for this test Func MapCreate() Local $aMap[1][2] $aMap[0][0] = 0 Return $aMap EndFunc Func MapRead($aMap, $sKey) For $i = 1 To UBound($aMap, 1) - 1 If $aMap[$i][0] == $sKey Then Return $aMap[$i][1] Next Return SetError(1, 0, "") EndFunc Func MapSet(ByRef $aMap, $sKey, $vVal) For $i = 1 To UBound($aMap, 1) - 1 If $aMap[$i][0] == $sKey Then $aMap[$i][1] = $vVal Return EndIf Next Local $iSize = UBound($aMap, 1) ReDim $aMap[$iSize + 1][2] $aMap[$iSize][0] = $sKey $aMap[$iSize][1] = $vVal $aMap[0][0] = $iSize EndFunc #EndRegion -
Hmm.. Seems one of the forum updates or something cleared the followers list, so I wasn't getting notifications of people posting here or I would have responded sooner... I didn't even catch that I didn't have the third parameter in this on the post or my local copy of that code... I have it in any of the stuff I do, it must have just slipped my mind to add it to the base while I was working on it, sorry about that! Using caleb41610's test script, on the code in the original post (after correcting that simple mistake!) will do 1000 connections in 10 seconds, where as Krsta's final code will do 1000 connections in 5 seconds... The reason for this is how accepting connections is handled. Mine makes processing client data a priority by always checking if any clients have sent something before checking the new connection queue and getting new clients in, where as Krsta's makes accepting new clients a priority, by only checking current client data when no new connections are queued. If I change mine around a bit and make it so it only calls Check() when $iSock = -1, I see similar performance, down to 1000 clients in 5 seconds (mine has rounded up to 6 seconds a few times, so its average is slightly slower than Krsta's). If I had to guess, mine is still slower because it uses a dynamic array size for the main client array instead of Krsta's fixed array size, but for the things I do with this code the slight performance hit it incurs is worth the benefit of a flexible max client limit. So it seems mine is still being bit in the butt by overhead in ReDim, and since Krsta isn't using ReDim, no butt-biting goes on there. This has shown me what a difference it can make to switch to fixed-size for the clients array if I ever have a need for a client that can accept connections more consistently though. Also I chose to do the dynamically re-sized 2d array for simplicity's sake, and for more flexibility, as max clients can be adjusted on-the-fly without requiring a restart (by just changing $MaxClients), and it would be much less work while developing off of this (as it was intended) to change a 2d array than it would be to create another 1d array, in my personal opinion. (Updated first post with the quick-fix I overlooked before) EDIT: I should also point out another down-side I hadn't thought of while initially writing this... With a fixed-size array, it tears through CPU cycles walking through the entire array each time, even if there isn't many clients connected. So if you've got it set to 10,000 total connections, it will have to walk through those 10,000 elements each time. With a dynamically-sized array, the number of elements will always only be the number of active clients, so if the limit is 10,000 but there are only 10 clients connected, the array will only be around 10 elements large(11 if you use one as an index). Just thought I'd throw that out there too for a bit more understanding of why I made things the way I did.
-
I've just made some more changes to it, this time to increase efficiency when large (over 1,000) active clients are connected and one or more clients disconnects. Turns out in this case that it is up to 500x faster, on my computer at least, to build a copy of the original array without the sub-elements you don't want and then overwrite the old array with the new copy than it is to use ReDim to re-size the one array. I would have figured the latter would have been much more efficient, but it seems there are always curve-balls in the game of programming. I've changed the original Sleep(1) call in the main loop to a custom sleep function (credit goes to monoceres for the basics behind that function) which takes delays in microseconds instead of milliseconds, because it turns out the lower-level function AutoIt's Sleep wraps appears to only be able to go down to ~10ms, so there was a decent gain in response time just by switching that over. I've got it set to 5000us (5ms) sleep delay in the example, but you can safely go down to 1000us (1ms) without much of a resource-usage hike, from my testing that is; Anything lower than 1000us doesn't seem to give much more of a performance increase, so diminishing returns, etc... I also corrected some more spelling (again... ), tweaked the little example echo server code in that base to better demonstrate my choice of why that line dealing with pulling packets from the buffer that many have said was incorrect is actually exactly how I intended it to function.
-
Thanks, glad to hear it's as useful to other as it is to me! PS: This bit of code shown below can be ignored/removed, it was some debug code that sneaked in to one of the changes I had made, and it seems I forgot to remove it before posting the updated version! >_< All this did is just show the total number of clients currently connected every second in the console, nothing direly important or code-breaking if removed. AdlibRegister("asdf", 1000) Func asdf() ConsoleWrite($Clients[0][0] & @CRLF) EndFunc
-
Yes, it probably could if it was implemented correctly, I have used this for quite a few projects myself. EDIT: Spelling.
-
If that is all your code, try putting TCPStartup() as the first line, that is needed to initialize sockets in AutoIt... Below is something I just whipped up that should work with the default example in the original post, although I have not actually tested this, it will at least give you an idea on what's what. TCPStartup() HotKeySet("{F5}", "SendData") Global $Sock = TCPConnect("127.0.0.1", 8080) While 1 Local $sRecv = TCPRecv($Sock, 8192) If $sRecv = "" Then ContinueLoop MsgBox(4096, "Server Reply", $sRecv) WEnd Func SendData() Local $sData = InputBox("Send To Server", "Enter the string of data you wish to send to the server...") If $sData = "" Then Return TCPSend($Sock, $sData & @CRLF) EndFunc After it runs, press F5 to bring up an input box, enter something simple in to it like "Hello" or such and press enter... you should instantly see a message box pop up saying the text you just sent to the server (which it echoed back).
-
Would you mind posting your client code so I could give it a stern looking-at, to see if I could spot the problem? If you'd rather not post it here, sending it in a PM to me would work as well... If telnetting to it works fine and the client doesn't, it sounds like the problem is with the client.
-
I've stated my reason for doing the buffer like I did, and that reason is that this is only the boiler-plate code with a very basic example. If that implementation is not what you are looking for, then making it work for your specific use-case is entirely up to you Although, I would not mind helping you with that if you need it.
-
Ok, finally got around to fixing that... $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1)) This is intended, it grabs all complete packets from the buffer and leaves any incomplete packets in the buffer, so if the client is still sending a large amount of data, it lets that packet get received completely while it is off checking other things. Actually parsing the packets is left up to the person implementing this in to their own project, but making a parser is fairly trivial, and can be done by using StringSplit($sRecv, @CRLF, 1) to create an array, where each element is a complete packet... From there you just have to loop through the array and process the packets as-necessary. This ensures that only a string of complete, ready-to-be-parsed packets are given to your own code, because crashes are bad The StringTrimLeft thing that removed the already-read packets from the buffer was an error which was taken care of. Finally the error of it skipping over buffered data until new data was received is also fixed, seems I just forgot to have it check the buffer and instead had it checking the data right out of TCPRecv. The code in the original post has been updated with these fixes, and thanks a lot for pointing out those bugs, they were pretty serious ones and I'm surprised I missed them!
-
Thanks for pointing those out, admittedly, the simple echo server stuff was added after-the-fact at like 4-5 in the morning so a friend could see some basic example for using it. I'm a bit embarrassed that I didn't catch those before posting this originally... As for the issue of not reading the entire buffer, I hadn't even noticed that at the time I wrote the example buffer code, I'll update the original post with the fixes later today, I'm not at a place where I can test the code edits currently.
-
Glad to be of assistance!
-
_WinAPI_SetConsoleTitle UDF (With detailed example!)
Kealper replied to Kealper's topic in AutoIt Example Scripts
This? Me likey a lot I have to admit, that Console.au3 is something I fully intend on staring at the source to... My console reading function stopped working when AutoIt dropped the raw file read mode, since I was getting console text by reading the device file "con"... Thanks for pointing me in the direction of this! -
_WinAPI_SetConsoleTitle UDF (With detailed example!)
Kealper replied to Kealper's topic in AutoIt Example Scripts
Thanks for thanking! I don't post many code snippets on here, but it is nice to see that the ones I do post are appreciated -
I've come across this problem myself... The problem is that TCPRecv is a non-blocking function, meaning it will return what data it has received so far instead of waiting for all of it, and since TCP is a stream-based protocol, there is no way for it to determine if your application's packet has been fully read by itself. Because of those two things I mentioned, what is happening is that when you call TCPRecv, it is only returning the data that has been sent to it so far (because sending data over a network is actually not instantaneous, it is just really fast). To fix this, you need to implement a receive buffer in your program. The buffer would temporarily hold the received data until your application has determined that the whole packet it is looking for has arrived. If speed is not an issue, the easiest way would just be to throw like a Sleep(100) in just above the TCPRecv call, giving your program just a bit more time to receive all of the data before you go to read it. This has it's drawbacks because it still has some corner-cases where it won't return all of the data, but it should fix most of them. If speed is an issue, then a more complex buffering system would have to be made...And I wouldn't mind helping with that if you were unable to figure out how to go about doing it. EDIT: Also forgot to mention that it isn't a problem with receiving null characters, the TCP functions don't seem to be null-terminated from my experience. SECOND EDIT: I whipped together a simple example to show what I mean by a receive buffer. This is a very basic "echo" server which listens for telnet connections, and when it gets them, it will echo back any message that you type as soon as you press the enter key. If you are using Microsoft's telnet client, this example will show exactly what I mean, since Microsoft's telnet client sends out letters as you type them. TCPStartup() Global $Listen = TCPListen("0.0.0.0", 1234) ;Listen on all addresses on port 1234 If @error Then ;Uh-oh! ConsoleWrite("Error! Couldn't listen for clients on port 1234! Is another instance of this example already running?" & @CRLF) Exit 1 ;Exit with error-code 1 EndIf While 1 Local $iSock = TCPAccept($Listen) ;Check for new connections If $iSock = -1 Then ContinueLoop ;If no new connections are present, go back to the top of the loop and check again ConsoleWrite("A new client has connected!" & @CRLF) ;A wild connection appears! Local $sBuffer = "" ;Create a local receive buffer variable While 1 ;Go in to a loop to read everything the client sends in to the buffer Local $sRecv = TCPRecv($iSock, 512) ;Write up to 512 characters at a time in to the buffer If @error Then ;If the client disconnected, stop right here and check for new clients again ConsoleWrite("Client has disconnected. Now waiting for more clients..." & @CRLF) ExitLoop EndIf If $sRecv = "" Then ContinueLoop ;Client sent no data, go check again... $sBuffer &= $sRecv ;Client did send data, throw this new data in to the buffer ConsoleWrite("Client sent: " & $sRecv & @CRLF) If StringInStr($sBuffer, @CRLF) Then ;If the client has sent an @CRLF (an enter button press), then do this TCPSend($iSock, "received: " & $sBuffer & @CRLF) ;Send their message they sent back to them $sBuffer = "" ;Empty the temporary buffer and start waiting for more data EndIf WEnd WEnd
-
Ok, so this has probably been posted before, but I was looking through the MSDN library randomly just a bit ago, and decided to play around a bit with some of the console-related functions. AutoIt can make basic console applications to provide users with some basic output (which is generally more efficient than outputting to a GUI), but wouldn't it be cool to be able to name your console windows just like you can name your GUI windows? Instead of it being called "C:\Users\Foobar\Desktop\MyEchoServer.exe" for instance, you could make your program call itself just "My Echo Server" and such. Here is the simple UDF on it's own, and below this is a nice little example detailing how you can use the function. ; #FUNCTION# ==================================================================================================================== ; Name ..........: _WinAPI_SetConsoleTitle ; Description ...: Change the AutoIt process's attached console title. ; Syntax ........: _WinAPI_SetConsoleTitle($sTitle[, $hDLL = "Kernel32.dll"]) ; Parameters ....: $sTitle - A string value. ; $hDLL - [optional] A handle value. Default is "Kernel32.dll". ; Return values .: True if the title was able to be changed, False if it was not able to be changed. ; Author ........: Ken "Kealper" Piper ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WinAPI_SetConsoleTitle($sTitle, $hDLL = "Kernel32.dll") Local $iRet = DllCall($hDLL, "bool", "SetConsoleTitle", "str", $sTitle) If $iRet[0] < 1 Then Return False Return True EndFunc And here is the example... For best results, save this to a file and compile it as a console application. If it isn't compiled as a console application, there is a quick and dirty DllCall in there to create a "dummy" console if it doesn't exist already which can serve to demonstrate the function anyways (but without any textual output). #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ;Create a new console window if it does not already exist, even if it is not compiled as a console executable. ;This DllCall is not part of the example, it only serves to ensure the example works correctly. ;Don't run through SciTE, the example will fail, and even this DllCall can't fix that. DllCall("Kernel32.dll", "bool", "AllocConsole") ;Don't just rely on this though, to get the most from this, compile as a console app! ;Begin actual example. ConsoleWrite("Keep an eye on the console's window title!" & @CRLF) Sleep(3000) ;First: Setting the title of your console window is as easy as this! _WinAPI_SetConsoleTitle("This is some custom text!") ;A simple count-down, so the first title change is visible for a few seconds before proceeding to the next example. For $i = 5 To 1 Step -1 ConsoleWrite("Proceeding in " & $i & "..." & @CRLF) Sleep(1000) Next ConsoleWrite("On to example two! This'll count to 50 and then exit." & @CRLF) ;Second: Something a bit more advanced. Changing the console's title rapidly. ;When changing the console's title rapidly, you should first open Kernel32.dll and then pass that handle ;as a second parameter to the function. This makes it use the open handle instead of having to open and ;close Kernel32.dll each time the function is called. This ends up making it more efficient. $Kernel32 = DllOpen("Kernel32.dll") ;Open Kernel32.dll. $Kernel32 now holds a handle to the opened file. For $i = 1 To 50 ;Count to 50 _WinAPI_SetConsoleTitle("Counting..." & $i, $Kernel32) ;Set the new title, and tell the function to use the open handle instead. Sleep(100) ;Wait 100ms, so the change can be easily seen by everyone. Without this, the change would happen too fast to notice. Next DllClose($Kernel32) ;Finally, because we like our resources, close the open handle since we no longer need it. ; #FUNCTION# ==================================================================================================================== ; Name ..........: _WinAPI_SetConsoleTitle ; Description ...: Change the AutoIt process's attached console title. ; Syntax ........: _WinAPI_SetConsoleTitle($sTitle[, $hDLL = "Kernel32.dll"]) ; Parameters ....: $sTitle - A string value. ; $hDLL - [optional] A handle value. Default is "Kernel32.dll". ; Return values .: True if the title was able to be changed, False if it was not able to be changed. ; Author ........: Ken "Kealper" Piper ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WinAPI_SetConsoleTitle($sTitle, $hDLL = "Kernel32.dll") Local $iRet = DllCall($hDLL, "bool", "SetConsoleTitle", "str", $sTitle) If $iRet[0] < 1 Then Return False Return True EndFunc
-
UDPRecv ignores TCPTimeout option
Kealper replied to Kealper's topic in AutoIt General Help and Support
That's actually why I was asking... I've got a potential buffer overflow problem that is partly being caused by each call to UDPRecv blocking for 100ms... A server I made for a chat can be taken down if a client is sending too much data to another client and it can some times lock up its instance of the interpreter (autoit3.exe actually completely stops responding until the offending client stops blasting it with data or gets disconnected)... This seems to only happen when the server is unable to empty TCPRecv's temporary buffer into a more permanent buffer variable fast enough. Any delays with TCP functions like the 1ms delay in every call to TCPRecv, or the 100ms delay with every call to TCPAccept can be removed just by setting that TCPTimeout option to 0... But the problem comes in when that server is also listening for UDP packets as well (as a type of echo for checking if the server is online), and that 100ms per call ends up being enough to drive it over the edge if multiple clients are transferring files or something else that requires heavy data usage a few times now. I'll admit I don't actually know if the 100ms delay in UDPRecv is completely needed... But if it is not, then it would be most helpful to either tie that delay in to the TCPTimeout option, or make a UDPTimeout option with a similar function. Meh, I guess I'm just rambling by now... -
Is using 'not' better than using '= 0'
Kealper replied to norry's topic in AutoIt General Help and Support
That speed test is flawed because it's relying on FileExists, which has to use the hard drive. Using the hard drive in any way will provide inaccurate results, since it can be artificially higher if the hard drive had to read elsewhere while the program was running, and because of hard drive caching. You want to stick with as simple as you can to get the best result for speed... I used this modified code below and got the result It seems from this more stripped down test, Not is faster than = 0 when spread out over 100k calls... The two "Control" things in there are 100k checks of just "If True Then" Modified speed test code: Control() Control() Test1() Test2() Test1() Test2() Func Test1() ConsoleWrite("Not" & @TAB) $timer = TimerInit() For $i = 1 To 100000 If Not True Then EndIf Next ConsoleWrite(TimerDiff($timer) & @CRLF) EndFunc Func Test2() ConsoleWrite("= 0" & @TAB) $timer = TimerInit() For $i = 1 To 100000 If Not True = 0 Then EndIf Next ConsoleWrite(TimerDiff($timer) & @CRLF) EndFunc Func Control() ConsoleWrite("Control" & @TAB) $timer = TimerInit() For $i = 1 To 100000 If True Then EndIf Next ConsoleWrite(TimerDiff($timer) & @CRLF) EndFunc EDIT: We should probably also say the CPU/RAM speed we have, since that could very well make a difference.. I've got a 1.83Ghz Intel Core 2 Duo with DDR2-667 ram. -
I've seen this for a while now but I never really got around to doing anything... It seems UDPRecv has a 100ms delay if nothing is recieved (which is to be expected), but it totally ignores the value set in the TCPTimeout option. I'm not sure if that is intended or if it is a bug so I figured I'd ask here before throwing it up on the trac so I knew what to file it as. I know "TCPTimeout" implies that it's only for TCP, but other things seem to use TCP and UDP interchangably in their names (TCPStartup/UDPStartup, etc) so I figured it could have just been accidentally left un-implemented in the UDPRecv code when that option was added, and that no one ever really brought it to everyone's attention. It just seems odd that you'd be able to control the delay for something like TCPAccept but not for UDPRecv, since there are things where having a 100ms wait after almost every UDPRecv call is not desirable... EDIT: I guess I should have formatted my question better when originally writing this, what I meant to ask was: Is there a reason why UDPRecv ignores the TCPTimeout option? Or is that a bug that should be filed in the trac? Below is code to show what I'm talking about with the delay, it waits about 100ms after each call to UDPRecv. UDPStartup() ;Make things like TCPAccept return instantly instead of blocking for the default ;100ms after no activity. Doing this is useful if your program does more than ;just wait for data on a specific socket. Opt("TCPTimeout", 0) ;Bind a random port, what port doesn't matter, it only needs to be a valid socket Global $Sock = UDPBind("0.0.0.0", Random(1, 65535)) While 1 $iTimer = TimerInit() $sRecv = UDPRecv($Sock, 512) ;Time how many milliseconds it takes to call UDPRecv and write time to stdout ConsoleWrite(TimerDiff($iTimer) & @CRLF) WEnd
-
No problem, glad it helped! I fixed a small bug which could cause a crash if a lot of connections and disconnections were happening. I've updated the source in the original post, and below is the section of code that I fixed. This is in the bottom of the Cleanup() function, the part that resizes the $Clients array: If $bTrim Then Local $iSize = UBound($Clients, 2) ;This line was modified Local $iCount = 1 Local $aTemp[1][$iSize] For $i = 1 To $Clients[0][0] If $Clients[$i][0] >= 0 Then ReDim $aTemp[$iCount + 1][$iSize] For $j = 0 To $iSize - 1 ;This line was modified $aTemp[$iCount][$j] = $Clients[$i][$j] Next $iCount += 1 EndIf Next $aTemp[0][0] = UBound($aTemp, 1) - 1 $Clients = $aTemp EndIf
-
Nice! It's actually kind of weird, I made something similar a few months ago that I never released that was essentially a pure AutoIt archiver with optional compression, and it's file format is almost exactly the same (with a few minor details, like my format doesn't have file hashes, because the thing it was intended to archive can have the possibility of corrupt files; It's intent was to be faster at storing many files in many subdirectories than zip).. I guess great minds think alike! EDIT: Although one thing I would like to make is a GUI version of mine, as it is CLI-only, because I'm lazy.
-
Ahh, didn't see the DLLs when I was just quickly giving it a try, after moving the two DLLs into the examples folder and running the examples as x86 it worked great! Nice job, the examples are very responsive!
-
Reading from serial ports with FileRead
Kealper replied to paulpmeier's topic in AutoIt Example Scripts
Some times I wish the raw read mode was not removed... Its removal also meant that random fun things like this can't be done as easily anymore -
Hmm... I was unable to get it to work properly It would start and exit instantly, printing some debug info in the console about frame rate and such, so I assume it was failing to start up OpenGL stuff. I'm using Windows 7 x64, but I tried running the examples as both x86 and x64, same result.