#1501 Re: mORMot 1 » Synopse mORMot benchmark » 2012-07-26 09:33:11

mpv

I think it depend of system type we develop. In my systems even small chance of data lost or database corruption is ABSOLUTELY IMPOSSIBLE. So for me preferred mode is FULL, even if I lost in productivity. For other system type it is not true. So my opinion - let developer decide in which mode mOROMot work.

#1502 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-26 07:39:21

mpv

In my project I write "name"="Arnaud", "fullName" = "AB" but "ID"=1, because ID is abbreviation. 
If you plane review framework for better JS support I propose to change "not expanded" format as listed below, or add new format type (I made it in such way  in my descendant of TSQLTableJSON):
<pre>
{"fields":[{"name":"ID","type":"int"},{"name":"Code","type":"string", "size": 32},{"name":"Caption","type":"string", "size": 128},{"name":"mi_owner","type":"float"},{"name":"mi_createdate","type":"date","dateFormat":"c"},{"name":"mi_createuser","type":"float"},{"name":"mi_modifydate","type":"date","dateFormat":"c"},{"name":"mi_modifyuser","type":"float"}],
"rowCount": 3,
"data":[[1,"code1","Caption code1",1,"2012-05-23T17:47:01",1,"2012-05-23T17:47:13",1],
          [2,"code2","Caption code2",1,"2012-05-23T17:47:01",1,"2012-05-23T17:47:13",1],
          [3,"code3","Caption code3",1,"2012-05-23T17:47:01",1,"2012-05-23T17:47:13",1]]
}
</pre>
I add fields array property with field definition (as I got it from provider), rowCount property for quick parse and frame each row in array. With such format use jQuery or ExtJS or other JS framework became pretty easy.
Field definition is optional.

#1503 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-25 13:57:00

mpv

And one remark: if we deal with JavaScript client (I mean browsers) it's good to start property name in JSON with a small letter. For example {"fieldCount":9,"rowCount":50,"values": [..]}. Name conversation in JS world: property start from small letter, constructor start from Upper case someObject.Create() but someObject.height. When I evaluate JSON in JS I got object and naming conversion is not mandatory, but is desirable. (There is no different in JS between constructor property or method - all is property, but method property if function type. So only one way to good reading code is naming conversation. JS is case sensitive).

#1504 Re: mORMot 1 » Synopse mORMot benchmark » 2012-07-25 13:42:23

mpv

I add my 5 cents to this benchmark.
1) For MS SQL result is: Write one - 340; Write trans - 318; Write batch - 337; Read one - 641; Read all - 91972;
2) But the main as for me begin if we test mORMot it true client-mORMot-dbatabase model (I mean remote client and mORMot server in HTTP mode. server thread count = CPU count*2):
3) We got linear scale. If 1 client send (in my example) 1000 "read all" requests and got 1000 response it take 3 sec. 2 client in one time - also 3 sec. 3 client in one time - also about 3 sec. And it's true until number of client <= number of thread. GREAT RESULT!
4) I asked my colleague to write .NET client to mORMot server and run it in DOS(denial of service) mode - 8 threads each with unlimited circle of "send request to mOROMot -> got result (100 record) -> write result into file "as is" - without parse". As result we have two same computer - one run mORMot server (database is oracle, no cache) - another - .NET DOS client. When .NET became 100% of processor time load, mORMot is 7% load and fill very good smile And it COOL!
5) I love mORMot. Arnaud the best!

#1505 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-25 11:30:26

mpv

AB, I test my system with large query (20000 - 500000 rows)  and find some way to increase performance:
in TSQLTableJSON.ParseAndConvert if we parse "not expanded" format we call GetRowCountNotExpanded function to calculate rowCount - it call take about 5% of all time. My propose is to add property rowCount for "not expanded" format  {"FieldCount":9,"rowCount":50,"Values": [..]}
We always know how many row we fetch from datasource, so it's simple. In my test I have 5% performance increase when remove GetRowCountNotExpanded call. (for 400 000 rows dataset from 4.09 to 3.88 sec on round trip for MS SQL).
Is it possible?

#1506 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-25 11:17:29

mpv

I had in mind for future versions of MS SQL (because it officially deprecated). Translation problems....

#1507 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-23 08:35:50

mpv

About blog entry http://blog.synopse.info/post/2012/07/1 … erformance
Using BULK operation in oracle (the same is true for MS SQL I think) give huge speed up not only due to the network latency, but in most case because of internal Oracle optimization for such query - in BULK mode all check  (unique index, constraint and so on) disabled for insert time and Oracle do it after inserting all record. Index rebuild and transaction logging made in the same way (after all inserts). All needed extents allocated at once. And so on. It's ease to reproduce that network latency is not a main problem - stored procedure in PL SQL give about 100x speed up too then using BULK.

#1508 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-22 10:40:53

mpv

@coblongpamor. Oh, I work with ClientDataSet many years ago - every thing is changed as I see. Now this parameter named OwnerData BeforeApplyUpdates(Sender: TObject; var OwnerData: OleVariant);
You must find corresponded TSQLRecord by ID from OwnerData and move modified fields from OwnerData to TSQLRecord instance.
In Delphy3 after this operation you must return NULL in OwnerData to avoid passing data to ClientData.RemoteServer - in current implementation I don't know.
And you must turn on ClientDataSet.LogChanges  after call TSQLTableToDataSet   (it Turned off for performance reason when fill dataSet with start data).

#1509 Re: mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-07-22 08:56:53

mpv

Hi!
We found some issue using CustomJSONSerializer. I need to define only custom writer for some class but use standard reader  - it not possible in current implementation. We made fix for this problem - I send sources to your mail. Please, include it in main branch. I make corresponding ticket also for tracking.

#1510 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-22 08:49:30

mpv

As for me, the easiest way to write TClientDataSet back to database in current implementation is handle BeforeApplyUpdates event and put dataset Delta back to TSQLRecord class. It's just 4 lines of code.....

About issue with FieldLength: in my implementation I use Columnus property of TSQLDBStatementWithParamsAndColumns (do not filleld for OleDB now) to determinate real size of string columns (it's not a biggest length of string in result data as in current mORMot implementation - field may be varchar(1000) but all row contains small string, and not possible to calculate max length via index, because I may write select fieldA+Left(fieldB, 2) from SomeTable, and real field size determinated by database.

#1511 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-20 15:55:46

mpv

@ab
For now I don't really need bulk insert - there is some architecture problems with bulk in my system..... (I need per record logic).
About ODBC - it become really need to mORMot when we migrate to x64 - there is no x64 OleDB drivers for latest MS SQL. But for now OleDB is enough.

But BULK operation in mORMot is cool! When I use oracle loader (it's a tools for import data using bulk insert) - the best result I reached is about 100000 rec/sec but in production server (UNIX, 12 Gb, 8 processor, very fast storage, Oracle optimization), so 50000 in simple computer is VERY GOOD result! Congratulations!

#1512 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-20 09:26:03

mpv

BATCH for Oracle is VERY GOOD FEATURE. AB - you are cool!

This is result for MS SQL(remote server on 100 Mb network): first for SQLOLEDB provider, second for SQLNCLI10 provider)
SQLOLEDB
{
    "Engine": "MSSQL",
    "CreateTableTime": "490.09ms",
    "NumberOfElements": 5000,
    "InsertTime": "14.84s",
    "InsertRate": 336,
    "InsertBatchTime": "17.75s",
    "InsertBatchRate": 281,
    "InsertTransactionTime": "12.81s",
    "InsertTransactionRate": 390,
    "InsertBatchTransactionTime": "16.26s",
    "InsertBatchTransactionRate": 307,
    "ReadOneByOneTime": "7.87s",
    "ReadOneByOneRate": 635,
    "ReadAllVirtualTime": "51.40ms",
    "ReadAllVirtualRate": 97264,
    "ReadAllDirectTime": "44.45ms",
    "ReadAllDirectRate": 112483,
    "ClientCloseTime": "7.75ms"
}
SQLCLI10
{
    "Engine": "MSSQL",
    "CreateTableTime": "649.59ms",
    "NumberOfElements": 5000,
    "InsertTime": "14.69s",
    "InsertRate": 340,
    "InsertBatchTime": "14.82s",
    "InsertBatchRate": 337,
    "InsertTransactionTime": "15.67s",
    "InsertTransactionRate": 318,
    "InsertBatchTransactionTime": "14.43s",
    "InsertBatchTransactionRate": 346,
    "ReadOneByOneTime": "7.79s",
    "ReadOneByOneRate": 641,
    "ReadAllVirtualTime": "52.35ms",
    "ReadAllVirtualRate": 95510,
    "ReadAllDirectTime": "54.36ms",
    "ReadAllDirectRate": 91972,
    "ClientCloseTime": "6.51ms"
}

May be use of ODBC give better result (but few years ago OleDB was faster - don't know for now).

#1513 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-12 08:36:43

mpv

About Oracle:
1) look on your Oracle performance. Try this example on your Oracle: http://www.sqlines.com/sql-server/inser … erformance. Example running time is the best result you can gain (in client-server life you code will be 2-5 times slower because of remote execution)
2) in your example you must commit transaction every 1000 execution for best performance (call Client.Commit; and when start new transaction) - Oracle don't like long transaction
3) to load big amount of data to Oracle the only way is to use Oracle bulk operation (supported by ODAC as I know) - 10-100 times faster compared to step by step insert. Not supported by mORMot yet.

About attributes - this is a good idea, but there is 2 problems:
1) mORMot work with Delphi versions (Delphi 5 and up) which dose not support attributes
2) new RTTI in Delphi (which support attribute) is VERY-VERY slow as for me.

#1514 Re: mORMot 1 » TOleDBConnection and multithread » 2012-07-06 15:04:34

mpv

AB, Hi!
I found some problems in mORMot when use TSQLDBConnectionProperties.GetFields and other database-structure related methods with TSQLDBConnectionPropertiesThreadSafe descendants.
These methods use MainConnection to get database structure, but in multithread (TSQLDBConnectionPropertiesThreadSafe ) it's not good, even with  OleDB.
The solution I propose is to make function TSQLDBConnectionProperties.GetMainConnection virtual and override it in

function TSQLDBConnectionPropertiesThreadSafe.GetMainConnection: TSQLDBConnection;
begin
  Result := ThreadSafeConnection;
end;

This will solve problem in easiest way.

I write a ticket for tracking.

#1515 Re: mORMot 1 » Highest performance when adding a lot of records to Oracle » 2012-07-06 14:31:59

mpv

If you do not use transaction and batch 600 insert per sec. is a good result. ( try same code with TQuery, for example )
If you want speed up your test on Oracle
1) use transaction and commit it for example every 1000 record inserted  (number of record inserted in one transaction depend of Oracle configuration)
2) use batch. (BatchAdd instead of Add in mORMot).

this is not mORMot limitation - such things must be done in any architecture.

#1516 Re: mORMot 1 » about blob column » 2012-07-03 11:19:14

mpv

Is you query return rows?
try this code:

if Query.Step then
  aParams.Resp := Query.ColumnBlob(0)
else
  // no rows return


TotalRowsRetrieved increased only after Step() call - see TOleDBStatement.Step source.

#1517 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-06-25 10:03:55

mpv

To @ab

As I remember when I use TClientDataSet (long time ago in Delphi 3) in "inmemory" way, setting TClientDataSet.LogChanges := False give GREAT performance increase. I think it's true in other Delphi versions too and must be used in TSQLTableToDataSet.

#1518 Re: mORMot 1 » MessageBox » 2012-06-01 12:57:04

mpv

Where is a free edition http://qooxdoo.org (it's a ExtJS1.0 branch)
But expensive - it's depend... If my project is commercial and a spend 1 month to do something with jQuery or a week with ExtJS I think ExtJS for $500  is better then 3 week of my salary.
If my project is for fun or academic - ExtJS is free in this case.

#1519 Re: mORMot 1 » leading zeros in JSON » 2012-05-30 12:00:24

mpv

2 ab.
I use overridden version of TSQLTable.GetJSONValues (when expant=false I write resp in {"fields":["fld1", "fld2"], "data": [[val1, val2,..valN],[val1, val2,..valN],...[]]} - it's more native for JavaScript client, but found a bug in your and my code

function TSQLTable.GetJSONValues(
       line:    if IsString(U^) then begin
must be:    if IsStringJSON(U^) then begin

it's important for string fields started from ZERO must me "code": "01", then IsStrint(U^) I got "code": 01 and JavaScript think code is integer..

may be exist other place where is changes necessary.....
I add ticket.

#1520 Re: mORMot 1 » MessageBox » 2012-05-30 11:33:08

mpv

I'm use http://www.sencha.com/ for rich client. Very good framework. But not simple.

#1521 Re: mORMot 1 » MessageBox » 2012-05-28 15:34:18

mpv

For example I'm implement binary data transfer by coding method-based service which take a multipart/form-data request(transfer file from client to server) as described in http://www.ietf.org/rfc/rfc1867.txt but with some limitation.
I use browser as client and this is only way to transfer binary data without base64 encoding (base64 not supported by IE<10).
In case of delphi client everything will be much easier, I think..

#1522 Re: mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-05-28 14:19:19

mpv

Thanks! All works as expected and your implementation is pretty clear

#1523 Re: mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-05-28 09:34:59

mpv

@ab Hi!
I'm implement HumanReadable writing and reading of set and enumeration property types.

I'm use existed HumanReadable param of  ObjectToJSON function - it should not break other projects that use mORMot if they use JSONToObject for reading.....

With my modification if HumanReadable=True then function ObjectToJSON write (for example)
property logLevel: TSynLogInfos read FlogLevel write SetlogLevel
as RawUTF8StringArray like
"logLevel":["sllDebug","sllTrace","sllWarning","sllError","sllCustom1","sllCustom2","sllCustom3"],

and
property logLevel:  TSynLogInfo  read FlogLevel write SetlogLevel
as
"logLevel": "sllDebug",

function JSONToObject read set and enum writed as integer or in new notation

I'm sent SQLite3Commons to your mail - please, review and if it's possible, include it in main branch.

I'm use this functionality to store configuration files of my application and to pass JSON to JavaScript client in debug mode.

#1524 Re: mORMot 1 » Additional method of TSQLRestClient.Update » 2012-05-18 07:38:08

mpv

Updating ID ( primary key) from client app - it seems like architecture problem. Updating ID usually need some additional steps like: lock tables; disable constraints; change ID; change  value of fields what foreign key on this ID; check integrity; enable constraints; The best way is not to update primary key.

#1525 Re: mORMot 1 » using POST with Client-Server Services » 2012-05-18 07:25:26

mpv

It's a solution, but it not good - setting async:false will block current browser page. The best(and right in javaScritp world) way is async call and making next request in success callback function. Something like jquery.ajax({....., success: function(){.... jquery.ajax(....);}).  There are many solutions how to get round the problem of nested function calls - events for example. (I don't know how do in in jquery - I'm not use jquery).

#1526 Re: mORMot 1 » using POST with Client-Server Services » 2012-05-17 11:54:37

mpv

In your case 403 Forbidden is not because a couple of miliseconds between two http requests, but because http request is going from browser in async way. Do each next request after getting response from previous, and all will be OK.
Pause is not a good solution.

#1527 Re: mORMot 1 » Getting Started Guide? » 2012-05-13 13:11:01

mpv

If you need a thousands of concurrent users ISAPI is not a best choice. The best performance is to use http.sys + IOCP (via mORMot THttpApiServer) and SynDBOracle for database access. In this case you:
1) do not need IIS and oracle client - only WinXP SP2+ and oci.dll smile
2) can easy implement in-memory server cache, session information storage and other feature
3) get VERY good performance

#1528 Re: mORMot 1 » How to get mORMot working for iOS using XE2? » 2012-05-11 14:57:50

mpv

Now mORMot (server part) use IOCP - it is only Windows technology. Anybody know - something similar exist in iOS?

#1529 Re: PDF Engine » Two Additional TPdfPageLayout » 2012-05-11 08:04:55

mpv

It's appear in PDF 1.5

I use this documentation when working with pdf:  www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
Quote:

PageLayout
(Optional) A name object specifying the page layout shall be used when the document is opened:
SinglePageDisplay one page at a time
OneColumnDisplay the pages in one column
TwoColumnLeftDisplay the pages in two columns, with odd-numbered pages on the left
TwoColumnRightDisplay the pages in two columns, with odd-numbered pages on the right
TwoPageLeft(PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left
TwoPageRight(PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right
Default value: SinglePage.

#1530 Re: Low level and performance » x32 and memory usage » 2012-05-10 14:14:59

mpv

I read your post about fast multi-thread Delphi applications as soon as found this site and use all you proposition!
I know about DWS, but I need the same language for client (browser) and server business logic, so SpiderMonkey is best for me.
SynScaleMM is ASAP to try.

#1531 Re: Low level and performance » x32 and memory usage » 2012-05-02 07:01:22

mpv

I create 2 thread per CPU core. On 24 (4 CPU x 6 core) server is 48 thread. So it 85Mb per thread. I use SpiderMonkey for Server-side business logic. SpiderMonkey Garbage Collection is hard operation, and I try to run it as late as possible for every thread, so lot of memory is good smile. (For example try to open 48 different tabs in FireFox and type about:memory in address bar  - it's a 10-20Mb per tab - in my case - per connected client). Some client may in this time upload big(I support up to 10Mb) files, I use transformation for different type of file to HTML via user business logic for use it later as file preview - it's requires in-memory operation. Other client may create big (100 or more page) reports. For report generating and file upload is possible to use temporary files of course, but for SpiderMonkey and file transformation more memory=best performance.
Thanks for reply!

#1532 Low level and performance » x32 and memory usage » 2012-04-30 11:21:54

mpv
Replies: 4

While mORMot is compiling using x32 compiler it's may be useful for us:
Q: I am using Windows x64 edition. How do I enable my applications to address more than 2GB RAM?
A: Add a line containing {$SetPEFlags $20} to the .dpr file. This will set the LARGE_ADDRESS_AWARE flag in the executable and Windows x64 will consequently give the process a full 4GB user address space instead of the usual 2GB.

Thank to FastMM4_FAQ.txt for this idea.

Delphi XE define const in Winapi.Windows for $20, and it's possible to write:
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

#1533 Re: mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-04-29 17:52:36

mpv

If you don't mind I can add it and post source to you..

#1534 Re: mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-04-28 10:52:31

mpv

@ab Please advise me how best to proceed: when I use JSONToObject and ObjectToJSON to read/write configuration files for  my application (config files is not plain and it's impossible to store it in ini) it's will be good to store Enumeration property in text representation (not as integer) to be a HumanReadable. For now I define one published property prop: RawUTF8 read ReadProp write SetProp. In setProp I do conversion of RawUTF8 to FProp: enum and in ReadProp back conversion. And one public property with enum value. But count of classes increasing and I tired to do in this way sad It's very easy in mORMot to implement writing enum property in text format when HumanReadable=TRUE (or adding additional param like EnumIsText default false - this way is better when use JavaScript as client). Is it possible to include this feature in the main branch?
Also it will be very good for JavaScript client of mORMot.
Thanks.

#1535 Re: Language » Smart Studio: mORMot, from Delphi to JavaScript » 2012-04-27 18:23:35

mpv

"Smart" project for delphi programmers is like the GWT for Java programmers. But I think that's a bad idea to write on one high level language and translate code to other high level language (with performance and functionality lost). JavaScript is a very good language when use it smartly smile I develop server part of my project usin Synopse for transport and database layer and SpiderMonkey emadding for business logic. SpiderMonkey internal (C and C++ code) is really beautiful! And VERY fast - compartible and even better than .NET. Client part is writn on Sencha (ExtJS) and it very usefull too. But there are many other JS framework for build UI, like  JQueryUI or Yahoo, qooxdoo.org (it's a guys from ExtJS team).

#1537 mORMot 1 » TOleDBConnection and multithread » 2012-04-25 12:28:13

mpv
Replies: 9

Refer to ticket http://synopse.info/fossil/tktview?name=213544b2f5.
The problem is more complex:
Call to TSQLDBConnectionPropertiesThreadSafe.ThreadSafeConnection usually made from inside HTTPserver thread, and corresponding CoInitialize call in HTTPserver thread context.
Call to TSQLDBConnectionPropertiesThreadSafe.Destroy is made from main thread, therefor call to CoUnInitialize is not made from thread in witch CoInitialize called.
As result we have "Missing TOleDBConnection.Destroy call in" in SynOleDB.finalization

The solution is to define event like THttpServerGeneric.OnHTTPThreadTerminate. (OnTerminate is unusable because of Synchronize)

With such type of event a write something like:

procedure MyServer_OnHTTPThreadTerminate(sender: TObject);
begin
  fMyCnnProp.EndCurrentThread;
end;

Arnaud, I sent patched SynCrtSock.pas for you.

#1538 Re: mORMot 1 » The mORMot attitude » 2012-04-25 12:13:03

mpv

I don't know about RTC, but mORMot and RO is like rocked and turtle if we spoke about speed. Especially for large numbers of clients.

#1541 mORMot 1 » JSONToObject and TJSONSerializer customization » 2012-04-07 09:29:14

mpv
Replies: 35

I add functionality to SQLite3Commons to allow custom implementation of read/write class to/from JSON.

Now in my code I do:

Tm3NamedCollection = class;
Tm3Val = class;
.....
initialization

SQLite3Commons.RegisterJSONRW(Tm3NamedCollection, m3NamedCollectionToJSON, m3JSONToNamedCollection);
SQLite3Commons.RegisterJSONRW(Tm3Val, m3ValToJSON, m3JSONToVal);

and then:

var
  nc: Tm3NamedCollection;
....
  res := ObjectToJSON(nc, true);

And it's read/write my type of classes via custom JSON serialization.

It's give me a possibility to use all power of your great implementation of JSON  with my classes.
Is it possible for you to add this code to SQLite3Commons? How can I attach modified SQLite3Commons.pas file for review?

#1542 Re: mORMot 1 » Interface based services » 2012-03-28 07:53:32

mpv

Yes, I see. Thanks. It's now possible to do params in queries - I post a suggestion.

#1543 Re: mORMot 1 » Interface based services » 2012-03-27 18:59:09

mpv
ab wrote:

@mpv

You are right.

I'll let services be running outside the global lock.
See http://synopse.info/fossil/info/a56cba70ce for the fix.

Thanks for the remark.

It's much better!
And adding
case URIMethod of
is a good idea – code becomes much more clear.
There is also a problem with SQL statement execute – I created ticket.

General remark - your framework is the best Delphy code I have seen for 15 years of developing. Very cool!

#1544 Re: mORMot 1 » Interface based services » 2012-03-25 09:40:16

mpv

In current realization of "Interface based services" any request to service is going by POST method, and all POST methods are blocked in RestServer.URI method by AcquireWrite(SessionID), therefore when using  "Interface based services" we do not have a true multithread server - all thread are blocking while one interface method is executing. It's bad sad  Do you plan to do multithreding (may be defining some method in interface what say the interface doesn't need blocking or move LaunchService from AcquireWrite block)?.

Board footer

Powered by FluxBB