NAVmoble - the pocket-sized ERP
Optimized for Microsoft Dynamics NAV and Windows Mobile powered devices

Wednesday, November 30, 2005

The first portable computer

While reading around, I was able to find a proof about how fast the technology goes forward. See a picture of the first "portable" computer called Osborne-1, created in 1981. It was sized to fit under an airplane seat and was armed with Basic,WordStar and SuperCalc. So it seems you had to buy an airplane to carry it. Now we buy bags and belts and pants with pockets. :)

Monday, November 21, 2005

SKU Matrix for Windows Mobile Version 5.0

Are you a looking for a Windows Mobile 5 brief feature list?
This is the place where you may start reading

Sunday, November 20, 2005

.NET Compact Framework 2.0 Performance and Reflection

   If you spent your time researching performance improvement tips, soon you will find that reflection is a great but expensive feature in terms of performance.
Let's see some metrics, then!
   My test environment is just the same as in my previous post
We've got HTC QTEC 9090, VS2005,CF2.0,Sql Ce 3.0.
I used the same database structure and 10000 rows to fetch. Every scenario makes 5 subsequent runs. Application is restarted before each test scenario run. Scenario 1 is not listed here , because it uses DataRow instances to represent database table rows.
The code is almost the same. I changed only the way the BObject instance is created. It is created by using Activator.CreateInstance method, this time.

List<BObject> boList = new List<BObject>();
...
IDataReader reader = cmd.ExecuteReader();
...
while(reader.Read())
{
//This was the old instance creation
//BObject bo = new BObject();


//This is the new extra time-consuming instance creation
BObject bo = (BObject)Activator.CreateInstance(typeof(BObject));
bo.id = reader.GetInt32(0);
bo.data1 = reader.GetString(1);
bo.data2 = reader.GetDateTime(2);
bo.data3 = reader.GetDouble(3);
boList.Add(bo);
}


I repeated the same testing scenarios and here come results:
Scenario 2: SqlCeDataReader
#Time[ms]Memory[bytes]Time increase[%]
11006496221699
283441125212142
382611295408136
482881422712143
58333952280129

Scenario 3-a:SqlCeResultSet,None
#Time[ms]Memory[bytes]Time increase[%]
11057696206497
290911125200133
390291295396131
490621422700129
59019952128133

Scenario 3-b:SqlCeResultSet,Insensitive
#Time[ms]Memory[bytes]Time increase[%]
115486996206427
214016112520029
313886129539628
414118142270029
51410595212830

Scenario 3-c:SqlCeResultSet,Scrollable,Updatable,Sensitive
#Time[ms]Memory[bytes]Time increase[%]
11405496206442
212494112520070
312369129539664
412471142270065
51240695212867


   We've got ~25-140 percents time increasing, due to using this resource hungry feature! There is also a small memory overhead. It is not as meaningful as the time increase. However the memory increase was stable across all the test scenario runs, that I've performed. It is interesting that testing scenarios 2 and 3-a(the faster data access methods) report far greater time increasing compared with the rest ones. The time diff. between scenario 3-a and 3-b in the previous test cases had a mean value of ~60%. In this case the diff. is only ~30% due to performance loss in scenario 3-a.
   One of the reasons, which motivated me to perform these tests was that Activator.CreateInstance pattern is very useful, when extendability and flexibility are required.
And while this pattern is frequently used in the desktop environment, it comes with a great cost in the CF world.

Saturday, November 12, 2005

.NET Compact Framework 2.0 Data Access Performance

Further reading .NET Compact Framework 2.0 Performance and Reflection

I took little of my time today to prepare a VS2005 SD project to test the performance differences between some of the SqlCe data access options. I have the following test environment:
Device: HTC QTEK 9090
OS: Windows Mobile 2003 SE
Dev.Env: VS2005 , CF2.0,SqlCe 3.0
I've created a table with the following Sql:

CREATE TABLE test1
(
id int IDENTITY NOT NULL,
data1 nvarchar(100),
data2 datetime,
data3 float
)


I've populated it with 10000 rows, using the following Sql:
insert into test1(data1,data2,data3)values('some string',getdate(),123)
I measured then the performance, while reading rows from SqlCe 3.0 by using the following testing scenarios:

scenario 1: DataSet, SqlCeAdapter
scenario 2: SqlCeDataReader
scenario 3-a: SqlCeResultSet, options None
scenario 3-b: SqlCeResultSet, options Insensitive
scenario 3-c: SqlCeResultSet, options Sensitive,Updatable, Scrollable

All scenarios were played using the following Sql statement:
SELECT id,data1,data2,data3 FROM test1

There is a significant difference between the first scenario and the rest ones. Scenario 1 fetches all rows into a DataSet. The rest fetch
rows into object instances defined like:
public class BObject
{
public int id;
public string data1;
public datetime data2;
public double data3;
}

The fetching code was like:
List<BObject> boList = new List<BObject>();
...
IDataReader reader = cmd.ExecuteReader();
...
while(reader.Read())
{
BObject bo = new BObject();
bo.id = reader.GetInt32(0);
bo.data1 = reader.GetString(1);
bo.data2 = reader.GetDateTime(2);
bo.data3 = reader.GetDouble(3);
boList.Add(bo);
}

Every scenario was executed 5 times and execution time and total memory reported by GC were written down. The application was restarted before each scenario test run. The results are as follows:
Scenario 1:DataSet
#Time[ms]Memory[bytes]
1101122096016
286731930176
385922189796
486562096160
586541930176

Scenario 2: SqlCeDataReader
#Time[ms]Memory[bytes]
1506952548
234531051124
334941151748
43414850952
53639953004

Scenario 3-a:SqlCeResultSet,None
#Time[ms]Memory[bytes]
15368952536
239041051156
339021151692
43964850896
53875952992

Scenario 3-b:SqlCeResultSet,Insensitive
#Time[ms]Memory[bytes]
112238952536
2108481051156
3108261151692
410917850896
510877952992

Scenario 3-c:SqlCeResultSet,Scrollable,Updatable,Sensitive
#Time[ms]Memory[bytes]
19928952536
282661051156
384441151692
48538850896
58460952992

What is obvious from first sight is that SqlCeResultSet has different performance characteristics depending on the options used. Also you may see that DataSet is on the first place in memory consumed. One interesting figure is the longer time neededd to execute test run 1 and that's because of the JIT compiling proces on the first code hit.It seems from this tests that using SqlCeReder should be preferred in strict fetching scenarios, although perf differenceses from SqlCeResultSet(None) are not quite meaningful. However, if one needs scrolling and updating, SqlCeResultSet is the best choice.Unfortunately, I have not written down the perf. status of the system componentsts like SqlCe memory, total system memory used ,etc.This will help getting better picture of the data access pros and cons.