Sunday, August 24, 2008

Real time image editing in JavaScript, with Firefox 3.1

"JavaScript? That little glue language written by Netscape to try to glue HTML with Java? What a pathetic excuse of a language! It failed its original mission, couldn't deliver 5% of the features of Java, nor 5% of the performance of Java! It's a semi-Java, a quasi-Java, it's the instant coffee of Java, the decaf version of Java, 1mg only, not enough caffeine."

Young JavaScript programmer playing Scott Evil, "But look, Dad! I'm running a freakin' real time image editing application in a freakin' web browser! With JavaScript!"

Look! Really!

p.s. I know full well that describing JavaScript as a light weight version of Java is completely wrong.

p.p.s. Here's the demo author's blog entry about the demo, with source code. And yes, the demo DID calculate the colors of the image pixel-by-pixel.

p.p.p.s. The demo runs under Opera 9.5 as well, with similar performance to Firefox 3.0. It doesn't work in Safari 3.1. IE (even IE8 beta) doesn't support canvas and has very bad JavaScript performance in general so there's no chance it can work within a few years. Boo, Microsoft.

Thursday, August 21, 2008

Watch out for when your iPhone 3G refuses to receive calls

I went out to Hang Hau for breakfast today, with my iPhone in my pocket. When I got back home, my mom asked me why I didn't answer her phone calls.

Hmm... maybe it's because I didn't take my headphones with me this morning? The ringtone is quite hard to hear in all the traffic noise you know. But as soon as my mom did a test call to my phone, I knew the problem is with the phone.

The phone never rang.

The phone was turned on and I could run apps and go online via wifi perfectly in it. There're 2 bars of signal from 3's service. But the phone part of it was like.. disabled! I couldn't call it from landline or from other mobile phones, and it couldn't call out. Worse, while the iPhone was on but not accepting any calls, the caller wasn't able to leave voice messages either. For a moment I was suspecting it was 3's problem. But the phone worked correctly after I rebooted it. So there must be some problem with my iPhone that prevented it from receiving calls and calling out.

The mobile phone part of the iPhone can crash silently. That's a big problem. I don't care too much if SFNetNews or Bloomberg crashes - though I would really appreciate it if Apple can stop them from crashing; But why can I miss calls with my phone turned on, connected with cell towers?

I tried to replicate the problem by killing the MobilePhone app in my iPhone and calling in, after the reboot. I could still hear the ringtone and answer the call, however. Something much more complicated than just an app crash must have happened this morning. Not enough memory left for the incoming call?

Wednesday, August 13, 2008

A taste of what's coming in CKEditor 3.0

CKEditor 3.0 will be a major rewrite to the very successful FCKeditor 2.6.x series. Currently it is still in the prototypal stage (read: most of the features are not done) but it's already showing some amazing functionalities.

e.g. This (sorry about the video artifacts):


You can view the screencast in its full resolution here.

It is not impossible with FCKeditor 2.6.x right now or other RTE libraries out there at the moment. But very little JavaScript trickery is needed to make it work with CKEditor 3.0, and the switching speed is very fast. Imagine a Wiki with that.

Things the iPhone 3G technical specs don't tell you...

You can get that by jailbreaking your iPhone and run sysctl -a in the terminal.

Here is what I have on my iPhone 3G. with 2.0.1 firmware:

kern.ostype = Darwin
kern.osrelease = 9.3.1
kern.osrevision = 199506
kern.version = Darwin Kernel Version 9.3.1: Sun Jun 15 21:37:01 PDT 2008; root:xnu-1228.6.76~45/RELEASE_ARM_S5L8900X
kern.maxvnodes = 640
kern.maxproc = 52
kern.maxfiles = 12288
kern.argmax = 262144
kern.securelevel = 0
kern.hostname = iPhone
kern.hostid = 0
kern.clockrate: hz = 100, tick = 10000, profhz = 100, stathz = 100
kern.posix1version = 200112
kern.ngroups = 16
kern.job_control = 1
kern.saved_ids = 1
kern.boottime = Tue Aug 12 20:13:51 2008

kern.nisdomainname =
kern.maxfilesperproc = 10240
kern.maxprocperuid = 26
kern.dummy = 0
kern.dummy = 0
kern.usrstack = 805306368
kern.dummy = 0
kern.dummy = 0
kern.dummy = 0
kern.exec: unknown type returned
kern.aiomax = 10
kern.aioprocmax = 4
kern.aiothreads = 2
kern.corefile = /cores/core.%P
kern.delayterm = 0
kern.shreg_private = 0
kern.proc_low_pri_io = 0
kern.usrstack64 = 8247063986311266304
kern.procname =
kern.speculative_reads_disabled = 0
kern.osversion = 5B108
kern.safeboot = 0
kern.rage_vnode = 0
vfs.hfs has 2 mounted instances
vfs.devfs has 1 mounted instance
hw.machine = iPhone1,2
hw.model = N82AP
hw.ncpu = 1
hw.byteorder = 1234
hw.physmem = 121634816
hw.usermem = 96317440
hw.pagesize = 4096
hw.epoch = 1
hw.vectorunit = 0
hw.busfrequency = 103000000
hw.cpufrequency = 412000000
hw.cachelinesize = 32
hw.l1icachesize = 16384
hw.l1dcachesize = 16384
hw.tbfrequency = 6000000
hw.memsize = 121634816
hw.availcpu = 1
user.cs_path = /usr/bin:/bin:/usr/sbin:/sbin
user.bc_base_max = 99
user.bc_dim_max = 2048
user.bc_scale_max = 99
user.bc_string_max = 1000
user.coll_weights_max = 2
user.expr_nest_max = 32
user.line_max = 2048
user.re_dup_max = 255
user.posix2_version = 200112
user.posix2_c_bind = 0
user.posix2_c_dev = 0
user.posix2_char_term = 0
user.posix2_fort_dev = 0
user.posix2_fort_run = 0
user.posix2_localedef = 0
user.posix2_sw_dev = 0
user.posix2_upe = 0
user.stream_max = 20
user.tzname_max = 255
kern.ostype: Darwin
kern.osrelease: 9.3.1
kern.osrevision: 199506
kern.version: Darwin Kernel Version 9.3.1: Sun Jun 15 21:37:01 PDT 2008; root:xnu-1228.6.76~45/RELEASE_ARM_S5L8900X
kern.maxvnodes: 640
kern.maxproc: 52
kern.maxfiles: 12288
kern.argmax: 262144
kern.securelevel: 0
kern.hostname: iPhone
kern.hostid: 0
kern.clockrate: { hz = 100, tick = 10000, tickadj = -1072645529, profhz = 100, stathz = 100 }
kern.posix1version: 200112
kern.ngroups: 16
kern.job_control: 1
kern.saved_ids: 1
kern.boottime: { sec = 1218543231, usec = 0 } Tue Aug 12 20:13:51 2008
kern.nisdomainname:
kern.maxfilesperproc: 10240
kern.maxprocperuid: 26
kern.ipc.maxsockbuf: 8388608
kern.ipc.sockbuf_waste_factor: 8
kern.ipc.somaxconn: 128
kern.ipc.nmbclusters: 3486
kern.ipc.soqlimitcompat: 1
kern.ipc.mb_normalized: 0
kern.ipc.sosendjcl_ignore_capab: 0
kern.ipc.sosendjcl: 1
kern.ipc.sorecvmincopy: 16384
kern.ipc.sosendminchain: 16384
kern.ipc.soqlencomp: 0
kern.ipc.njclbytes: 0
kern.ipc.njcl: 0
kern.ipc.sbspace_factor: 8
kern.ipc.maxsockets: 128
kern.dummy: 0
kern.usrstack: 805306368
kern.aiomax: 10
kern.aioprocmax: 4
kern.aiothreads: 2
kern.corefile: /cores/core.%P
kern.delayterm: 0
kern.shreg_private: 0
kern.proc_low_pri_io: 0
kern.posix.sem.max: 10000
kern.usrstack64:
kern.tfp.policy: 2
kern.procname:
kern.speculative_reads_disabled: 0
kern.osversion: 5B108
kern.safeboot: 0
kern.lctx.max: 8192
kern.lctx.count: 0
kern.lctx.last: 1
kern.rage_vnode: 0
kern.tty.ptmx_max: 127
kern.sleeptime: { sec = 1218607962, usec = 525806 } Wed Aug 13 14:12:42 2008
kern.waketime: { sec = 1218608306, usec = 11 } Wed Aug 13 14:18:26 2008
kern.hibernatefile:
kern.bootsignature:
kern.hibernatemode: 0
kern.monotonicclock: 1218648807
kern.maxnbuf: 558
kern.nbuf: 558
kern.flush_cache_on_write: 0
kern.always_do_fullfsync: 0
kern.sugid_scripts: 0
kern.affinity_sets_mapping: 1
kern.affinity_sets_enabled: 1
kern.singleuser: 0
kern.bootargs:
kern.memorystatus_kev_failure_count: 0
kern.memorystatus_level: 50
kern.msgbuf: 4096
kern.wq_timer_interval_msecs: 40
kern.wq_max_run_latency_usecs: 500
kern.wq_reduce_pool_window_usecs: 3000000
kern.wq_stalled_window_usecs: 20000
kern.secure_kernel: 1
kern.wakereason: usb
vm.loadavg: { 0.00 0.29 0.39 }
vm.swapusage: total = 0.00M used = 0.00M free = 0.00M
vm.cs_debug: 0
vm.cs_force_hard: 0
vm.cs_force_kill: 0
vm.user_wire_limit: -2302491336873346024
vm.global_user_wire_limit: -4602390231608460264
vm.cs_blob_size_max: 38768
vm.cs_blob_size_peak: 419168
vm.cs_blob_count_peak: 172
vm.cs_blob_size: 411472
vm.cs_blob_count: 164
vm.cs_validation: 1
vm.vm_page_free_target: 374
vm.shared_region_persistence: 1
vm.shared_region_version: 3
vm.shared_region_trace_level: 1
net.local.stream.recvspace: 8192
net.local.stream.sendspace: 8192
net.local.dgram.recvspace: 4096
net.local.dgram.maxdgram: 2048
net.local.inflight: 0
net.inet.ip.portrange.hilast: 65535
net.inet.ip.portrange.hifirst: 49152
net.inet.ip.portrange.last: 65535
net.inet.ip.portrange.first: 49152
net.inet.ip.portrange.lowlast: 600
net.inet.ip.portrange.lowfirst: 1023
net.inet.ip.forwarding: 0
net.inet.ip.redirect: 1
net.inet.ip.ttl: 64
net.inet.ip.rtexpire: 2400
net.inet.ip.rtminexpire: 10
net.inet.ip.rtmaxcache: 128
net.inet.ip.sourceroute: 0
net.inet.ip.intr_queue_maxlen: 50
net.inet.ip.intr_queue_drops: 0
net.inet.ip.accept_sourceroute: 0
net.inet.ip.fastforwarding: 0
net.inet.ip.keepfaith: 0
net.inet.ip.subnets_are_local: 0
net.inet.ip.use_route_genid: 1
net.inet.ip.check_route_selfref: 1
net.inet.ip.linklocal.in.allowbadttl: 1
net.inet.ip.check_interface: 0
net.inet.ip.maxfrags: 216
net.inet.ip.maxfragsperpacket: 128
net.inet.ip.maxfragpackets: 108
net.inet.ip.maxchainsent: 8
net.inet.icmp.maskrepl: 0
net.inet.icmp.icmplim: 250
net.inet.icmp.timestamp: 0
net.inet.icmp.bmcastecho: 1
net.inet.icmp.log_redirect: 0
net.inet.icmp.drop_redirect: 0
net.inet.tcp.rfc1323: 1
net.inet.tcp.rfc1644: 0
net.inet.tcp.mssdflt: 512
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.sendspace: 131072
net.inet.tcp.recvspace: 131072
net.inet.tcp.keepinit: 75000
net.inet.tcp.rexmt_thresh: 2
net.inet.tcp.rfc3465: 1
net.inet.tcp.maxseg_unacked: 8
net.inet.tcp.slowlink_wsize: 8192
net.inet.tcp.reass.overflows: 0
net.inet.tcp.reass.cursegments: 0
net.inet.tcp.reass.maxsegments: 217
net.inet.tcp.drop_synfin: 1
net.inet.tcp.tcp_lq_overflow: 1
net.inet.tcp.delayed_ack: 3
net.inet.tcp.blackhole: 0
net.inet.tcp.log_in_vain: 0
net.inet.tcp.socket_unlocked_on_output: 1
net.inet.tcp.packetchain: 50
net.inet.tcp.ecn_negotiate_in: 0
net.inet.tcp.ecn_initiate_out: 0
net.inet.tcp.newreno: 0
net.inet.tcp.local_slowstart_flightsize: 8
net.inet.tcp.slowstart_flightsize: 1
net.inet.tcp.path_mtu_discovery: 1
net.inet.tcp.sack_globalholes: 0
net.inet.tcp.sack_globalmaxholes: 65536
net.inet.tcp.sack_maxholes: 128
net.inet.tcp.sack: 1
net.inet.tcp.rtt_min: 1
net.inet.tcp.background_io_enabled: 1
net.inet.tcp.isn_reseed_interval: 0
net.inet.tcp.strict_rfc1948: 0
net.inet.tcp.icmp_may_rst: 1
net.inet.tcp.pcbcount: 8
net.inet.tcp.do_tcpdrain: 0
net.inet.tcp.tcbhashsize: 128
net.inet.tcp.minmssoverload: 0
net.inet.tcp.minmss: 216
net.inet.tcp.always_keepalive: 0
net.inet.tcp.msl: 15000
net.inet.tcp.background_io_trigger: 5
net.inet.tcp.sockthreshold: 0
net.inet.tcp.out_sw_cksum_bytes: 2439757
net.inet.tcp.out_sw_cksum: 32018
net.inet.tcp.in_sw_cksum_bytes: 46445398
net.inet.tcp.in_sw_cksum: 41658
net.inet.tcp.win_scale_factor: 3
net.inet.udp.checksum: 1
net.inet.udp.maxdgram: 9216
net.inet.udp.recvspace: 41600
net.inet.udp.pcbcount: 5
net.inet.udp.blackhole: 0
net.inet.udp.log_in_vain: 0
net.inet.udp.out_sw_cksum_bytes: 264471
net.inet.udp.out_sw_cksum: 3750
net.inet.udp.in_sw_cksum_bytes: 376819
net.inet.udp.in_sw_cksum: 3501
net.inet.ipsec.def_policy: 1
net.inet.ipsec.esp_trans_deflev: 1
net.inet.ipsec.esp_net_deflev: 1
net.inet.ipsec.ah_trans_deflev: 1
net.inet.ipsec.ah_net_deflev: 1
net.inet.ipsec.ah_cleartos: 1
net.inet.ipsec.ah_offsetmask: 0
net.inet.ipsec.dfbit: 0
net.inet.ipsec.ecn: 0
net.inet.ipsec.debug: 0
net.inet.ipsec.esp_randpad: -1
net.inet.ipsec.esp_port: 0
net.inet.ipsec.bypass: 1
net.inet.raw.recvspace: 8192
net.inet.raw.maxdgram: 8192
net.link.ether.inet.send_conflicting_probes: 1
net.link.ether.inet.keep_announcements: 1
net.link.ether.inet.log_arp_warnings: 0
net.link.ether.inet.sendllconflict: 0
net.link.ether.inet.proxyall: 0
net.link.ether.inet.useloopback: 1
net.link.ether.inet.maxtries: 5
net.link.ether.inet.apple_hwcksum_rx: 1
net.link.ether.inet.apple_hwcksum_tx: 1
net.link.ether.inet.host_down_time: 20
net.link.ether.inet.max_age: 1200
net.link.ether.inet.prune_intvl: 300
net.key.debug: 0
net.key.spi_trycnt: 1000
net.key.spi_minval: 256
net.key.spi_maxval: 268435455
net.key.int_random: 60
net.key.larval_lifetime: 30
net.key.blockacq_count: 10
net.key.blockacq_lifetime: 20
net.key.esp_keymin: 256
net.key.esp_auth: 0
net.key.ah_keymin: 128
net.key.prefered_oldsa: 0
net.key.natt_keepalive_interval: 20
debug.wdtlog: 2114u0 2114u0 2100m0 2000m0 1914u0 1914u0 1914u0 1914u0 1900m0 1800m0 1714u0 1714u0 1714u0 1714u0 1700m0 1600m0 1514u0 1514u0 1514u0 1514u0 1500m0 1400m0 1314u0 1314u0 1314u0 1314u0 1300m0 1200m0 1110u0 1110u0 1110u0 1110u0 1100m0 1000m0 909u0 909u0 909u0 909u0 900m0 800m0 709u0 709u0 709u0 709u0 700m0 600m0 507u0 507u0 507u0 507u0 500m0 400m0 307u0 307u0 307u0 307u0 300m0 200m0 107u0 107u0 107u0 107u0 100m0 0m0
debug.marvel_debug: 136 136
debug.lowpri_max_waiting_msecs: 200
debug.lowpri_max_window_msecs: 200
debug.lowpri_IO_window_inc: 50
debug.lowpri_IO_initial_window_msecs: 100
debug.bpf_maxdevices: 256
debug.bpf_maxbufsize: 524288
debug.bpf_bufsize: 4096
debug.iokit: 0
hw.ncpu: 1
hw.byteorder: 1234
hw.memsize: 121634816
hw.activecpu: 1
hw.optional.floatingpoint: 1
hw.packages: 1
hw.tbfrequency: 6000000
hw.fixfrequency: 24000000
hw.prffrequency_max: 51500000
hw.prffrequency_min: 51500000
hw.prffrequency: 51500000
hw.memfrequency_max: 137333333
hw.memfrequency_min: 137333333
hw.memfrequency: 137333333
hw.l1dcachesize: 16384
hw.l1icachesize: 16384
hw.cachelinesize: 32
hw.cpufrequency_max: 412000000
hw.cpufrequency_min: 412000000
hw.cpufrequency: 412000000
hw.busfrequency_max: 103000000
hw.busfrequency_min: 103000000
hw.busfrequency: 103000000
hw.pagesize: 4096
hw.cachesize: 0 0 0 0 0 0 0 0 0 0
hw.cacheconfig: 0 16384 16384 1 32 4 0 0 0 0
hw.cpufamily: -1879695144
hw.cpu64bit_capable: 0
hw.cpusubtype: 6
hw.cputype: 12
hw.logicalcpu_max: 1
hw.logicalcpu: 1
hw.physicalcpu_max: 1
hw.physicalcpu: 1
machdep.alignmenttrap: 0
security.mac.seatbelt.debug: 0
security.mac.seatbelt.profile_refcount: 15
security.mac.seatbelt.qtnstate_refcount: 0
security.mac.seatbelt.cred_label_refcount: 5
security.mac.seatbelt.disable_builtins: 0
security.mac.vnode_enforce: 1
security.mac.vm_enforce: 1
security.mac.sysvshm_enforce: 1
security.mac.sysvsem_enforce: 1
security.mac.sysvmsg_enforce: 1
security.mac.system_enforce: 1
security.mac.socket_enforce: 1
security.mac.proc_enforce: 1
security.mac.posixshm_enforce: 1
security.mac.posixsem_enforce: 1
security.mac.pipe_enforce: 1
security.mac.iokit_enforce: 0
security.mac.file_enforce: 0
security.mac.device_enforce: 1
security.mac.mmap_revocation_via_cow: 0
security.mac.mmap_revocation: 0
security.mac.max_slots: 8


Interesting bits:
  1. The CPU has a maximum frequency of 412MHz, but I don't know whether it scales down its running frequency in power saving mode or not. Outside info says it's running at 620MHz.
  2. The CPU comes with 32KB of L1 cache, 16KB for data and 16KB for instructions. There's no sign of any L2 cache.
  3. Apple has chosen to run the ARM CPU in little endian mode.
  4. The CPU comes with an FPU as well.
  5. The CPU chip seems to be something called S5L8900(X?) from Samsung. Samsung's datasheet says it's an ARM CPU with built-in PowerVR MBX 3D graphics.
  6. The usable memory size is exactly 116MB. DRAM chips don't come in non-round numbers, the closest guess to the total physical DRAM size would be 128MB. So, 12MB is gone for other uses... graphics?
  7. It doesn't seem to use any swap memory at all. So if the 116MB runs out, your apps would surely crash.
  8. There're a few hw.memfrequency entries in the iPhone's sysctl listing which do not exist in Macintosh computers. It seems to indicate the iPhone's memory is running at roughtly 137MHz, I wonder if there's any DDR trickery involved.
  9. There's a "net.inet.ip.forwarding" entry which is set to 0 by default but it can be set to 1. In Linux that is the first step in making an NAT router.