Jump to content


Popular Content

Showing content with the highest reputation since 12/24/18 in all areas

  1. 6 points
    This release addresses problems with disabled IDE themes and Delphi 10.2 Tokyo releases below 10.2.3 (and some smaller bugs): https://www.mmx-delphi.de/2018/12/31/bugfix-release-for-mmx-code-explorer/
  2. 5 points
    OT: I liked the depressive design, it fit well with the daily frustrating experience with the IDE. 👿
  3. 4 points
    Yes ist must be the last unit, but the real problem is the IDE not finding the correct Unit....... We should not need a third-party tool for these kind of functionality. It should be work out of the Box, that's the reason for a IDE!!!
  4. 4 points
    Here is what we usually do: Store logs in a dedicated folder, with proper read policy. -> especially under Unix, all background daemons run with a dedicated user, and the log files have chmod 640 to restrain read access. Always run the logs in Verbose mode, even on production, unless the execution environment is really constrained. (you never know what will happen, and detailed logs is a need for proper investigation, especially on production) -> you need a logging solution which is fast, and can log dozen MB/s with no performance penalty (e.g. our SynLog.pas unit writes in a background thread) Rotate logs to keep history as long as possible -> SynLog.pas has built-in SynLZ-compression of the logs for very fast and efficient rotation Never log passwords, or such sensitive information. -> password are always stored and persisted in salted + hashed form - but when transmitted as parameters, or as settings, they should be encrypted - even a naive encryption may be enough like with a TSynPersistentWithPassword class from SynCommons.pas -> more generally, sensitive information should be handled in memory with strong cryptography, e.g. via our cross-platform CryptDataForCurrentUser() from SynCrypto.pas Have a way to hide unexpected content, when log is automated. -> in mORMot.pas, you can register some sensitive types which parameters will be logged as "***" during SOA automated logging of calls. Ensure all those policies are always setup by default, and on all supported platforms -> today, we should ensure that Linux execution should be not weaker than Windows as a target (and it is easy to make executable safer under Linux) Optionally use a third-party SaaS solution to store your logs in the long term, with proper encryption and search abilities -> like https://livemon.com - server-side written in object pascal 🙂 Most of it is available out-of-the-box in http://mormot.net
  5. 3 points
    I just wanted to say a public BIG THANKS to Mr. Fierens from TMS for his amazing and outstanding support: Today (which is a SUNDAY) I mailed him the description of a small bug. ONE HOUR LATER I got the bug fix attached as source code file in the mail. I never had a product (TMS ALL ACCESS) with such outstanding support quality!
  6. 3 points
  7. 3 points
    If I had a dime for every time some "simple test code" ended in production... 😋
  8. 3 points
  9. 3 points
    Please amend the title. The title should IMO reflect the contents of the post, which "-------" does not.
  10. 3 points
    Please allow me to disagree. I have made non-trivial use of System.Threading in PyScripter (used by thousands of users) without any problems. The main issue I know of with the library is RSP-11267. You can see a fix in that report, but even without the fix you can work around the issue by using a different mechanism for signalling task to stop As for Parallel.For I have not used it extensively, but you can see some code of mine in this StackOverflow question that I think is now used in a commercial product. An issue with thread creation by Parallel.For (RSP-21177) has been fixed in Rio. Advantages of System.Threading: By far the easiest way to use tasks (as opposed to threads) in your delphi application Nice interface using anonymous methods Avoids third-party dependencies It provides usage statistics that can be used for diagnostic purposes Nowadays, it provides good performance out of the box, but you can still fine-tune the way it works if you are prepared to dig-in It uses state-of-the-art synchronization techniques @Primož Gabrijelčič can correct me on this, but by reading his book "Delphi High Performance", I think, that depending on the type of use, is competitive if not faster than his own OmniThreadLibrary The Parallel library, like many other new features of Delphi (e.g. Generics) got a bad reputation, due to the many bugs in the early days. Unfortunately. trust is easy to lose and very hard to rebuild. But the library does deserves some love from Embarcadero (fixing remaining issues) and Delphi users.
  11. 3 points
    A while ago, after my post on Known IDE Packages in Delphi I wrote a the KnownIdePackagesManager tool which lists those packages, allows to disable and enable some of them and also set the package description for those packages that don’t have a meaningful description. Today, I updated the tool to support Delphi 10.3 Rio. https://blog.dummzeuch.de/knownidepackagesmanager-tool/
  12. 2 points
    G+ is slightly different. As Owner or Moderator you can only remove posts or comments, not edit them. A post that is removed from a community, remains on the profile of the original poster. I am already missing G+ a lot.
  13. 2 points
     @Primož GabrijelčičAt least in Rio it seems to work OK: program Project2; {$APPTYPE CONSOLE} uses WinApi.Windows, System.Diagnostics, System.Threading; procedure TestParallel; Var TaskArray: array [1..100] of ITask; begin for var I := Low(TaskArray) to High(TaskArray) do TaskArray[I] := TTask.Create(procedure begin Sleep(100); end).Start; TTask.WaitForAll(TaskArray); end; begin var SW := TStopWatch.StartNew; //TThreadPool.Default.SetMinWorkerThreads(50); TestParallel; WriteLn(SW.ElapsedMilliseconds); WriteLn; Var TPS := TThreadPoolStats.Default; WriteLn('WorkerThreadCount: ', TPS.WorkerThreadCount); WriteLn('MinLimitWorkerThreadCount: ', TPS.MinLimitWorkerThreadCount); WriteLn('MaxLimitWorkerThreadCount: ', TPS.MaxLimitWorkerThreadCount); ReadLn; end. Output on an 8 processor machine: 1370 WorkerThreadCount: 9 MinLimitWorkerThreadCount: 8 MaxLimitWorkerThreadCount: 200 Output with TThreadPool.Default.SetMinWorkerThreads(50); 233 WorkerThreadCount: 50 MinLimitWorkerThreadCount: 50 MaxLimitWorkerThreadCount: 200 With TParallel.&For it works differently and the number of threads created relate to the number of processors.
  14. 2 points
    Heh, I actually donated that SafeGuard code to JCL many years ago. They modified the name a little, but not the concept. It works, but I am not sure if all guarded objects will be released on an exception. You'll have to test that. The advantage is indeed that you don't have to cast or anything. You use the original object you created. Yesterday, I even wrote a better approach, using records an implicit and explict casts. That one is certain to work and does not need a cast and the pointer can be used as if it were the actual object (by implicit cast). type IObjectGuard<T: class> = interface function Value: T; end; TObjectGuard<T: class> = class(TInterfacedObject, IObjectGuard<T>) private FValue: T; public constructor Create(Obj: T); destructor Destroy; override; function Value: T; end; SmartPtr<T: class> = record private FGuard: IObjectGuard<T>; public class operator Explicit(const Obj: T): SmartPtr<T>; class operator Implicit(const Ptr: SmartPtr<T>): T; end; { TObjectGuard<T> } constructor TObjectGuard<T>.Create(Obj: T); begin FValue := Obj; end; destructor TObjectGuard<T>.Destroy; begin FValue.Free; inherited; end; function TObjectGuard<T>.Value: T; begin Result := FValue; end; { SmartPtr<T> } class operator SmartPtr<T>.Explicit(const Obj: T): SmartPtr<T>; begin Result.FGuard := TObjectGuard<T>.Create(Obj); end; class operator SmartPtr<T>.Implicit(const Ptr: SmartPtr<T>): T; begin if Ptr.FGuard <> nil then Result := Ptr.FGuard.Value else Result := nil; end; And it can be used like: var Bob, Fred, Jack: TTalking; begin Bob := SmartPtr<TTalking>(TTalking.Create('Bob')); Fred := SmartPtr<TTalking>(TTalking.Create('Fred')); Jack := SmartPtr<TTalking>(TTalking.Create('Jack')); Fred.Talk; Bob.Talk; raise Exception.Create('Error Message'); Jack.Talk; Writeln('This is the end of the routine'); end; As you can see, this also creates guards. They do work, even with the Exception. All are freed when the exception occurs.
  15. 2 points
    Yes. Check that 67372036 is the same as hex $04040404, in other words, 4 bytes, each with value 4. FillChar fills bytes, even if you pass a UInt32 or even a UInt64. It will only take the low byte and multiplicate that.
  16. 2 points
    And perhaps adjust your gustatory preferences as a daily deluge of beluga caviar may make employers nervous about you salary demands
  17. 2 points
    Nowadays you can use code like this: procedure TForm1.Button1Click(Sender: TObject); begin ScaleBy(14, 10); end; But make sure, that you do not call this too often, because all sizes of VCL controls are integers. That is why, when you call ScaleBy, some rounding happens, and over time you will get loss of precision.
  18. 2 points
    Of course not. However parallel programming is not a piece of cake. There are so many ways you can shoot yourself in the foot and then blame the library.
  19. 2 points
    Make a small testcase to demo the bug so others can confirm it or point to error in code.
  20. 2 points
    You are working with Unicode strings so you will always get varUString. I don't know what you have against varUString. Surely you don't want to go back to ANSI strings which is what varString represents. VarAsType returns a variant. That's why you need a typecast to obtain other types. The entire question seems massively over complicated. In fact this is a common theme of the questions you ask. Don't take that the wrong way. But my most important advice to you is to try to simplify. You seem regularly to get tied in knots because you don't reduce the complexity in your thinking. In this instance, surely, you should be working with the user input as text. No need at all for variants in my opinion. Simply use TryStrToInt to check if a string value can be treated as an integer. And if there really is some need for variants due to motivations we cannot see then take care to understand what types they can hold. Make sure that you only ever add Unicode strings and integers and therefore only need to deal with those two var types. Raise assertion exceptions if you encounter other types. Make sure that you have good testing in place. Now, you probably think that you haven't got time for testing but what many people don't realise is that testing saves you time. Testing is what allows you to make changes to code without fear of breaking it.
  21. 2 points
    A more general answer: You should not fetch all columns, run a full table scan and transfer all rows to your application. Nothing wrong with full table scan. Access was pretty good at SELECT everything from everywhere but SQL database simply don't work that way. a) select dedicated columns - list the columns you want to retrieve b) limit the number of rows c) a) + b) retrieve a well defined result set Introducing an index on a table emulates record oriented database. When it comes to online transaction retrieve columns using indices. Single lines should be treated as single lines and well defined result sets as well defined result sets. In general it's not wise to transfer data that is not required. You simply start to lock more data than should be treated or just retrieve the key values and requery. NexusDB ist one example for the best of both worlds. In a '4GL' like environment data is retrieved from the server, put into a local buffer (maybe on the app-server side) and the application logic refers to the data stored in those buffers. We would call those buffers in-memory data-set. Kinda LUW. Also in such cases a) makes lots of sense. In such environments you will have to live with a limited cache per user which is pretty helpful. If you want to reduce the traffic use a middleware or allow db access components to handle the pain for you. FireDAC and other components allow you to fine tune what you want to retrieve (Fetch Options). Those settings allow to lesser the pain and as you pointed out that works. The problem behind the scenes is Entity Relationship. Entity Relationship is about the insane idea to impose semantics on master-data and treat those as anything else but lookup tables. There is no such thing as 'master-data'. It's nothing but time independent transactional data. I fairly remember a data model that does still hold anything but time dependent what was called master-data once. From the very logic maintaining transactional data where there is no transaction makes no sense. If you have a server-side process on the server-side unless you don't get the data from another source too. Paginating results: Fetch what you need an fetch on demand. That works no matter what implementation technology is used, because it's the way things are intended to be.
  22. 2 points
    It’s time for a gift to all Delphi developers, a new Release of GExperts. Happy Holidays! (But do spend some time with your family rather than testing GExperts. 😉 ) I blogged about the new features already. There were also several bug fixes. ... https://blog.dummzeuch.de/2018/12/22/gexperts-1-3-12-experimental-twm-2018-12-22-released/
  23. 2 points
    This is simple to answer. Measure the time of the program running. Everything else is pointless. Don't guess performance questions. Measure.
  24. 2 points
    Hey, good idea: https://github.com/DelphiPraxis/The-Drag-and-Drop-Component-Suite-for-Delphi
  25. 1 point
    That's excellent, thanks Andrea. Hope you're feeling better and had a nice christmas break. Regards Stuart